为什么Django让Python看起来很难看?

2024-03-29 04:56:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我开始使用Python编程语言是因为它的设计理念、它伟大的社区以及对我来说最重要的是它优美的语法。不过,最近我有点灰心丧气。在我试图定制Django时,我遇到了一些代码,我认为在语法上可以更简洁。我绝不是一个经验丰富的Python程序员,事实上,我只是在过去几个月里正确地使用它。我很感激你的见解和观点。在

下面是我遇到的一些代码示例:

为什么需要刀砍?在

from django.contrib.admin.util import get_model_from_relation, \
    reverse_field_path, get_limit_choices_to_from_path

这能写得更优雅些吗?在

^{pr2}$

有一件事我不明白,为什么每个and语句的if语句后面的代码在不同的行上?在

def has_output(self):
    if isinstance(self.field, models.related.RelatedObject) \
       and self.field.field.null or hasattr(self.field, 'rel') \
       and self.field.null:
        extra = 1
    else:
        extra = 0
    return len(self.lookup_choices) + extra > 1

这看起来一团糟!在

def choices(self, cl):
    from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
    yield {'selected': self.lookup_val is None
                       and not self.lookup_val_isnull,
           'query_string': cl.get_query_string(
                           {},
                           [self.lookup_kwarg, self.lookup_kwarg_isnull]),
           'display': _('All')}
    for pk_val, val in self.lookup_choices:
        yield {'selected': self.lookup_val == smart_unicode(pk_val),
               'query_string': cl.get_query_string(
                               {self.lookup_kwarg: pk_val},
                               [self.lookup_kwarg_isnull]),
               'display': val}
    if isinstance(self.field, models.related.RelatedObject) \
       and self.field.field.null or hasattr(self.field, 'rel') \
       and self.field.null:
        yield {'selected': bool(self.lookup_val_isnull),
               'query_string': cl.get_query_string(
                               {self.lookup_kwarg_isnull: 'True'},
                               [self.lookup_kwarg]),
               'display': EMPTY_CHANGELIST_VALUE}

请不要误会我的意思,我并没有伤害到Django的许多贡献者,相反,我真的很佩服他们,我很感激。我很感激,也许是我对Python本身缺乏经验,或者是让语法看起来不干净的代码片段实际上是Python编程语言的核心特性。在

在这个问题上,我提出这个问题的真挚和强烈的讨论。如果您没有任何有助于贡献的内容,请不要回复。

谢谢你


Tags: and代码fromselffieldgetstringcl
3条回答

至少对于\来说:通常希望行最多包含80个字符(这有很多原因;这样更容易阅读或同时打开多个文件,不必滚动、约定/传统等)。\可以将一个(逻辑)行拆分为多个实际行,而不会导致缩进错误。在

第一个例子,没有反斜杠,可以写下来

^{1}$

注意你必须向右滚动才能看到整个过程,这很尴尬。将这些输入保持在80个字符的另一个选择是

^{pr2}$

但现在必须重复导入的模块,这很难看。最终归结为风格/个人偏好的问题。在

更一般地说,库代码看起来凌乱或非常规的情况并不少见—有时为了显示更好的接口,您牺牲了实现的整洁性。尤其是Django经常犯这种罪。例如,用于声明模型的语法,或者用于定制管理站点的语法,或者使用关键字参数进行数据库查询的整个业务的语法都非常好用,但是实现所有这些功能的代码可能很难让人绞尽脑汁。在

1)您需要斜杠,因为Django通常(但不总是)遵循pep8,其中的行最多应该有80个字符。不过,更好的方法是:

^{1}$

通常应避免\。在

2)本规范没有任何不雅之处。只需创建查找所需的属性。为什么你觉得它不优雅?你希望这个怎么写?在

需要再短于3)行。可以使用()重写并缩短:

^{pr2}$

然而,由于Django使用python2.4(我认为他们很快或已经在升级版本),所以他们不能使用inline if-else。在

另一方面,也可以用更短的方式写:

def has_output(self):
    if isinstance(self.field, models.related.RelatedObject) \
       and self.field.field.null or hasattr(self.field, 'rel') \
       and self.field.null:
        return len(self.lookup_choices) > 0
    else:
        return len(self.lookup_choices) > 1

但是我觉得原来的方法通过使用extra变量稍微清晰了一点。这里你需要一个注释,为什么它是0或1。有了额外的你不需要评论,它是非常清楚的。我不喜欢评论,所以我更喜欢第一种方式:-)

4)这看起来确实很混乱。我认为最好把它分成三个更小的方法,每个方法都有可能产生一些结果。但是我不确定python2.4(或python2.5)是否允许从子例程中产生(我有一些模糊的记忆,这是后来甚至在py3中引入的)。不管怎样,我会把这些字典的创建放在一个单独的方法中,因为它看起来很不寻常。我更喜欢这样:

def choices(self, cl):
    from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
    yield self._some_default_choice()
    for pk_val, val in self.lookup_choices:
        yield self._choice_from_lookup_choices(pk_val, val)
    if isinstance(self.field, models.related.RelatedObject) \
       and self.field.field.null or hasattr(self.field, 'rel') \
       and self.field.null:
        yield self._some_conditional_choice()

当然,我会为子方法使用一些更有意义的名称,但我看不到完整的上下文,也不知道这些选择是什么。在

最后:

你在这里看到的是Python被推到了极限。Django是一个大框架。有一些特性是Django是一个大型项目的结果,现在已经开发了几年,人们学习新东西。幸运的是,Django开发人员正在慢慢地删除他们认为是错误的东西,例如,更改django1.4中的默认项目结构,弃用这些内容,并碰撞python版本。实际上,从阅读django代码和提问中可以学到很多东西。你也许可以通过尝试重构一些代码,然后学习,为什么它不那么容易,为什么它必须保持原样;-)尝试一下,它会很有趣的:-)

I appreciate that maybe it's my lack of experience with Python itself or that bits of code that make the syntax look unclean are in-fact core features of the Python programming language.

就这样。当你继续编码时,你会意识到你所经历的一切都是新鲜事物的结果。这种类型的代码在任何语言中都会发生,因为这种语言只会描述响应消息的对象和函数之间的通信。在

一个好的练习就是浏览一下代码库并对其有一个感觉。一段时间后,您将习惯于所表达的代码和关系。在

总而言之,“丑陋”并不是Python独有的,但是当你开始熟悉Python语言并在不知不觉中熟练地使用这种语言时,你很快就会感觉到它只是代码。在

相关问题 更多 >