一般来说,出于以下几个原因,您不应该隐藏内置函数:
list成为内置的list,等等但也有一些例外。
在类属性中使用内置名称在运行时根本不会隐藏任何内容,尽管在评估时可能会隐藏任何内容。这种模式很常见:
class Foo:
def __init__(self, foo_id: int) -> None:
self.id = foo_id
Run Code Online (Sandbox Code Playgroud)
Foo().id直到我们在构造函数中绑定它才被绑定。这里没有发生阴影。使用 来id表示“身份”是非常常见的,它可能比任何替代方案(如obj_id或identity)更好,并且没有人会期望Foo().id成为内置的id。
如果您使用数据类,这可能涉及阴影:
@dataclass
class Foo:
# id refers to the builtin `id`
id: int = 0 # assigning a default for the example
# id referes to `Foo.id`, which has the typehint int
foo = Foo(id="id of foo")
# foo.id refers to the *instance* id, which is actually a string.
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们简单地做了shadow id。我们无法在评估时使用它。但无论如何,在定义(而不是构造)类时,您可能不应该获取对象的 id。由于数据类的工作方式,我们最终id在实例上得到了一个单独的实例foo(如此处所示,甚至不必是正确的类型!)。共有三个命名空间在起作用:封闭命名空间(这id意味着它通常所做的事情)、未实例化类的命名空间Foo(其中id是 0)和对象的命名空间foo(其中id是字符串)。我们已经在第二个中进行了隐藏,但无论如何我们稍后不会在该名称空间中执行任何操作。
如果这样做可以提高清晰度,那么对一个小函数中的内置函数进行隐藏可能是可以接受的,因为该函数永远无法使用被隐藏的对象。这两个可能都很好:
def get_object_from_db(id: int) -> CustomObj:
...
def find_enclosing_dir(filename: str) -> Pathlib.Path:
f = _find_file(filename)
dir = f.parent
some_logic_to_validate(dir)
return dir
class Foo:
def __init__(self, id: int) -> None:
self.id = id
Run Code Online (Sandbox Code Playgroud)
第一个示例是id函数中的阴影,其中我们关心的唯一“id”是我们正在检索以构建CustomObj. 不过,obj_id在这里使用可能会更清楚。第二个示例隐藏dir并将其用于目录。 dir并且类似的自省工具不太可能在这段代码中使用;再次parent_dir 可能会更清楚,但这里的阴影是一种风格选择。在第三个示例中,我们id在 for 的构造函数中进行隐藏Foo。同样,我们现在不能使用id,但我们的代码可以说更干净。
一般来说,避免阴影是一件好事。在小函数或方法中,为了清晰起见,隐藏内置函数可能是有意义的。只有当它增加清晰度时才应该这样做,并且如果发生一些变化而进行重构以避免阴影的工作量很小。至少该功能应该能够舒适地显示在一个屏幕上。类属性可以不受惩罚地“隐藏”(因为它们根本不隐藏),但只有少数名称可以像这样使用。 id或许dir有道理,但Foo.listorFoo.str可能不如描述性名称那么清晰。
| 归档时间: |
|
| 查看次数: |
536 次 |
| 最近记录: |