Python 使用类级原语的正确方法
Python中类变量的处理方式对我来说毫无意义。类变量的范围似乎取决于它的类型!基本类型被视为实例变量,复杂类型被视为类变量:Python 使用类级原语的正确方法,python,Python,Python中类变量的处理方式对我来说毫无意义。类变量的范围似乎取决于它的类型!基本类型被视为实例变量,复杂类型被视为类变量: >>> class A(object): ... my_class_primitive = True ... my_class_object = ['foo'] ... >>> a = A() >>> a.my_class_primitive, a.my_class_object (True, ['foo'
>>> class A(object):
... my_class_primitive = True
... my_class_object = ['foo']
...
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_object.append('bar')
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
>>> a.my_class_primitive = False
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
请有人解释一下:
该特性作为Python类定义的缓存形式存在 类定义本身中定义的属性被视为类的
静态属性。e、 g.不应修改它们
我敢肯定,这个决定是在假设您在修改静态属性方面遵循最佳实践的情况下做出的;) 该功能作为Python类定义的缓存形式存在
类定义本身中定义的属性被视为类的静态属性。e、 g.不应修改它们
我敢肯定,这个决定是在假设您在修改静态属性方面遵循最佳实践的情况下做出的;) 您应该做的适当比较是:
>>> class A(object):
my_class_primitive = True
my_class_object = ['foo']
>>> a = A()
>>> b = A()
>>> a.my_class_primitive = False
>>> a.my_class_object = ['bar']
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
这不是你认为你看到的。这种“奇怪”的行为是由可变性的概念引起的。也就是说,您正在更改分配给my_class_object
属性的对象,同时将不同的对象分配给my_class_primitive
。在第一种情况下,它适用于所有实例(因为这是一个对象),而在第二种情况下,它适用于单个实例(您正在更改其属性)
你不是唯一一个陷入这种困惑的人。要查看可变性如何影响代码的另一个示例,您可以选中此项:您应该进行的适当比较如下:
>>> class A(object):
my_class_primitive = True
my_class_object = ['foo']
>>> a = A()
>>> b = A()
>>> a.my_class_primitive = False
>>> a.my_class_object = ['bar']
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
这不是你认为你看到的。这种“奇怪”的行为是由可变性的概念引起的。也就是说,您正在更改分配给my_class_object
属性的对象,同时将不同的对象分配给my_class_primitive
。在第一种情况下,它适用于所有实例(因为这是一个对象),而在第二种情况下,它适用于单个实例(您正在更改其属性)
你不是唯一一个陷入这种困惑的人。要查看可变性如何影响代码的另一个示例,可以检查以下内容:
类属性存储在A中
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
因此b.my_class_object
也会受到影响:
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
赋值a.my\u class\u primitive=False
向a
添加一个新的实例属性。它将一个键值对放在a.\uuu dict\uuu
中:
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
因此b
不受影响:
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
使a.my\u class\u原语
返回在a.中找到的键的值。而不是在a.中找到的键的值
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
类属性存储在A中
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
因此b.my_class_object
也会受到影响:
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
赋值a.my\u class\u primitive=False
向a
添加一个新的实例属性。它将一个键值对放在a.\uuu dict\uuu
中:
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
因此b
不受影响:
>>> b.my_class_primitive, b.my_class_object
(True, ['foo', 'bar'])
使a.my\u class\u原语
返回在a.中找到的键的值。而不是在a.中找到的键的值
>>> A.__dict__
>>> <dictproxy {'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'my_class_object': ['foo'],
'my_class_primitive': True}>
>>> a = A()
>>> a.my_class_primitive, a.my_class_object
(True, ['foo'])
>>> b = A()
>>> b.my_class_primitive, b.my_class_object
(True, ['foo'])
>>> a.my_class_primitive = False
>>> a.__dict__
>>> {'my_class_primitive': False}
>>> a.my_class_primitive, a.my_class_object
(False, ['foo', 'bar'])
这与原始和复杂无关。当附加到a.my_class_对象
时,修改现有对象。分配给变量时,不会对其进行修改。如果您像对待布尔值一样对待列表,则列表也存在同样的“问题”:
>>> class Foo(object):
... x = []
...
>>> i1 = Foo()
>>> i2 = Foo()
>>>
>>> i1.x = 5
>>>
>>> print(i2.x)
[]
当您获得i1.x
时,Python将查看属性的i1.\uuuu dict\uuuu
。如果在那里找不到它,它会在该对象的每个父类的\uuu dict\uuu
中查找,直到找到为止(或抛出AttributeError
)。返回的对象根本不必是i1
的属性
当您指定给i1.x
时,您专门指定给i1.x
要修改类属性,请参考类,而不是实例:
>>> class Foo(object):
... x = 2
...
>>> i1 = Foo()
>>>
>>> Foo.x = 5
>>>
>>> print(i1.x)
5
这与原始和复杂无关。当附加到a.my_class_对象
时,修改现有对象。分配给变量时,不会对其进行修改。如果您像对待布尔值一样对待列表,则列表也存在同样的“问题”:
>>> class Foo(object):
... x = []
...
>>> i1 = Foo()
>>> i2 = Foo()
>>>
>>> i1.x = 5
>>>
>>> print(i2.x)
[]
当您获得i1.x
时,Python将查看属性的i1.\uuuu dict\uuuu
。如果在那里找不到它,它会在该对象的每个父类的\uuu dict\uuu
中查找,直到找到为止(或抛出AttributeError
)。返回的对象根本不必是i1
的属性
当您指定给i1.x
时,您专门指定给i1.x
要修改类属性,请参考类,而不是实例:
>>> class Foo(object):
... x = 2
...
>>> i1 = Foo()
>>>
>>> Foo.x = 5
>>>
>>> print(i1.x)
5
区别不在于基本类型和复杂类型之间,而在于赋值和修改变量之间
如果使用instance.name=value
,则始终会分配新的实例变量,即使已经存在同名的类属性
例如:
>>> class A(object):
... my_class_primitive = True
... my_class_object = ['foo']
...
>>> a = A()
>>> a.my_class_primitive = False
>>> a.__class__.my_class_primitive
True
>>> a.__dict__
{'my_class_primitive': False}
>>> a.my_class_object is a.__class__.my_class_object
True
在这里,添加到列表的行为不同之处在于,当您在类实例上执行属性查找时,它将首先查找实例变量,如果没有具有该名称的实例变量,它将查找类属性。例如:
>>> class A(object):
... my_class_primitive = True
... my_class_object = ['foo']
...
>>> a = A()
>>> a.my_class_primitive = False
>>> a.__class__.my_class_primitive
True
>>> a.__dict__
{'my_class_primitive': False}
>>> a.my_class_object is a.__class__.my_class_object
True
因此,当您执行a.my\u class\u object.append(x)
时,您正在修改任何实例都可以访问的class属性。如果要执行a.my_class_object=x,则它不会以任何方式修改class属性,它只会创建一个新的实例变量。原语和