一个对象的属性集和命名空间有什么区别?

3

对象的属性集形成了一个命名空间。要访问该属性,必须指定命名空间:obj.attr。这是否意味着对象的属性只是在特定命名空间(对象名称)中定义的名称?还是有所区别?例如,模块中名称的引用是属性引用:modname.function表达式中,modname是一个模块对象,funcname是它的属性,(参见:9.2),但是当您定义以下函数时,函数的命名空间和其属性之间有明显的区别:

>>> def aFunction():
    x=1
    y=2
    z=3
    #three names have been defined in the local namespace,
    #but aren't considered to be attributes of aFunction from what I understand.

我很困惑。请有人详细解释一下,阐述对象的命名空间和其属性之间的区别是什么?


1
这里的问题在于您定义不清楚"对象命名空间"的概念。函数有一个属性命名空间,每次对函数的调用都有一个本地变量命名空间。这些是不同的命名空间,但是通过以"对象命名空间"的方式思考,你最终把这些概念混淆了。命名空间可以从概念上与对象关联的方式不止一种。 - user2357112
1个回答

2

让我引用文档:

命名空间是从名称到对象的映射。大多数命名空间当前都实现为Python字典,但通常没有任何区别(除了性能),并且将来可能会更改。命名空间的示例包括:内置名称集合(包含诸如abs()和内置异常名称之类的函数);模块中的全局名称;以及函数调用中的本地名称。在某种意义上,对象的属性集也形成一个命名空间。关于命名空间需要知道的重要事情是,在不同命名空间中的名称之间绝对没有关系;

所以,正如@user2357112支持Monica所说的评论:

命名空间与对象可以有多种概念上的关联方式。

Kent Johnson也很好地谈到了它:(链接)

Another way to think of it is, a namespace is a place where names are looked up. When you use a bare name (not an attribute), it is looked up in the local namespace, then the global namespace, then the built-in namespace. For example:

y = 2  # Defines y in the global (module) namespace

def f():
  x = 1 # Defines x in the local (function) namespace

  # This looks up x, finds it in the local namespace
  # looks up abs, finds it in the built-in namespace
  print abs(x)

  # This looks up y, finds it in the global namespace
  print y

Note that none of the above namespaces have a related __dict__ attribute, the namespace mappings are not stored that way.

Objects also define a sort of namespace, where attributes are defined and looked up. The dict containing the namespace of an object is itself stored as an attribute of the object, called __dict__. So __dict__ is an implementation detail of the way object attributes are stored.

As a beginner, it is important to understand the way bare names are looked up (local, global, built-in namespace) and a bit about the way attributes work. You don't have to be concerned with the implementation details such as __dict__.

您可以使用 dir() 函数来探索不同的命名空间,该函数:

如果没有参数,则返回当前本地作用域中的名称列表。如果有一个参数,则尝试返回该对象的有效属性列表。

def foo(a):
    if a == 3:
        b = 1
    else:
        c = 1
    print("Local function namespace: ", dir())


a = 2
b = 3
foo.custom_attr = "some attr"
foo(a)
foo(b)
print("Global namespace: ", dir())
print("foo object namespace via dir: ", dir(foo))
print("foo object namespace via __dict__: ", foo.__dict__)
print("Built-in namespace: ", dir(__builtins__))

输出:

Local function namespace:  ['a', 'c']
Local function namespace:  ['a', 'b']
Global namespace:  ['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'foo']
foo object namespace via dir:  ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'custom_attr']
foo object namespace via __dict__:  {'custom_attr': 'some attr'}
Built-in namespace:  ['ArithmeticError', 'AssertionError', 'AttributeError', [...]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接