Python:self vs type(self)和类变量的正确使用
在Python中使用类变量时,可以通过“self”(由于引用)或“type(self)”(直接)访问和(如果它是可变的)直接操作它,而不可变变量(例如整数)在使用“self”时显然会被新的实例对象遮蔽 因此,在处理Python类变量时,是否最好/Pythonic始终使用“type(self)”来处理从类方法中引用的类变量 (我知道有时不赞成使用类变量,但当我使用它们时,我希望以一致的方式访问它们(如果它们是不可变类型,则使用一种方式;如果它们是可变类型,则使用另一种方式)Python:self vs type(self)和类变量的正确使用,python,class-variables,Python,Class Variables,在Python中使用类变量时,可以通过“self”(由于引用)或“type(self)”(直接)访问和(如果它是可变的)直接操作它,而不可变变量(例如整数)在使用“self”时显然会被新的实例对象遮蔽 因此,在处理Python类变量时,是否最好/Pythonic始终使用“type(self)”来处理从类方法中引用的类变量 (我知道有时不赞成使用类变量,但当我使用它们时,我希望以一致的方式访问它们(如果它们是不可变类型,则使用一种方式;如果它们是可变类型,则使用另一种方式) 编辑:是的,如果修改不
编辑:是的,如果修改不可变对象的值,则会得到一个新对象。修改可变对象的值的副作用就是导致这个问题的原因——“自我”将为您提供一个引用,您可以使用它来更改类变量,而无需对其进行阴影处理,但如果您为其分配了一个新对象,它将对其进行阴影处理。使用classname.classvar或type(self).classvar或self.\uuuu class\uuuuuuuuuuuu确保您始终使用类变量,而不仅仅是对其进行阴影处理(尽管如下文所述,子类使这一点复杂化)。您可能希望使用实际的类型名来访问它们,而不是
self
或type(self)
你所看到的效果与可变性无关
class Foo(object):
x = []
def __init__(self):
self.x = [1]
\uuuu init\uuuuu
中的赋值将创建一个新列表,并将其赋值给实例属性x
,忽略class属性,即使Foo.x
是一个可变对象。无论何时您想要赋值给属性,都需要使用它实际定义的对象
请注意,在继承的情况下,通过type(self)
修改属性会失败:
class Foo(object):
x = 1
def modify_x(self, x):
type(self).x = x
class Bar(Foo): pass
Foo().modify_x(2) # modifies Foo.x
Bar().modify_x(3) # modifies Bar.x, the wrong attribute
您可能希望使用实际的类型名称访问它们,而不是
self
或type(self)
你所看到的效果与可变性无关
class Foo(object):
x = []
def __init__(self):
self.x = [1]
\uuuu init\uuuuu
中的赋值将创建一个新列表,并将其赋值给实例属性x
,忽略class属性,即使Foo.x
是一个可变对象。无论何时您想要赋值给属性,都需要使用它实际定义的对象
请注意,在继承的情况下,通过type(self)
修改属性会失败:
class Foo(object):
x = 1
def modify_x(self, x):
type(self).x = x
class Bar(Foo): pass
Foo().modify_x(2) # modifies Foo.x
Bar().modify_x(3) # modifies Bar.x, the wrong attribute
我会提出这些建议供参考
Beautiful is better than ugly.
Simple is better than complex.
Readability counts.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
If the implementation is hard to explain, it's a bad idea.
我的建议是使用直接属性引用,因为这可能是语言设计者想要的
我会提出这些建议供参考
Beautiful is better than ugly.
Simple is better than complex.
Readability counts.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
If the implementation is hard to explain, it's a bad idea.
我的建议是使用直接属性引用,因为这可能是语言设计者的意图。在与其他人离线交谈后(以及根据@wwii对其中一个答案的评论),在不显式嵌入类名的情况下,最好的方法是使用self.\uuu class.\uuuu.attribute
(虽然有些人使用type(self).attribute,但它会导致其他问题。)在与其他人离线交谈后(根据@wii对其中一个答案的评论),在不显式嵌入类名的情况下,最好的方法是使用self.\uuuu class\uuuuuuuu.attribute (虽然有些人使用type(self.attribute),但它会导致其他问题。) 在常见情况下,它们的工作原理是相同的(可能您应该使用YouClass.NameAttribute以避免以后继承时出现问题)。 简而言之,在Python 3.5之前就存在差异。问题在于问题#24912(在所有情况下都不允许分配)。例如:像int这样的不可变类型是alocated staticalli,而HEAPTYPE在从ALOGATEDclassASING停止时意外地规则。 在常见情况下,它们的工作原理是相同的(可能您应该使用YouClass.NameAttribute以避免以后继承时出现问题)。
简而言之,在Python 3.5之前就存在差异。问题是问题#24912(在所有情况下都不允许分配).Example:像int这样的不可变类型是alocated staticalli,HEAPTYPE规则意外地从alowingclassassingment停止。你能展示一些示例代码吗?类方法是什么意思?你是指用@classmethod修饰的方法,还是仅仅是类的方法?我是指cla的常规方法下面有一些示例代码-尽管需要一些澄清,但似乎问题本身已经被理解。你能展示一些示例代码吗?你所说的类方法是什么意思?你是指用@classmethod修饰的方法,还是只指类的方法?我指的是类的常规方法。下面有一些示例代码-尽管需要进行一些澄清,但问题本身似乎还是被理解了。您关于显式使用类名的观点很有趣……尽管我想知道是否有一种更干净的方法可以做到这一点,而不是显式地将类名洒在整个列表中。例如,如果您指定了一个新列表“[1]”,那么是的您将对类变量进行阴影处理。但是,如果更改现有列表(例如,append),则不会创建新对象(而更改不可变项将始终创建新对象-阴影处理仅通过使用类名或“self”进行调解)@MartyMacGyver:你不能改变一个不可变的对象。你只能重新分配它,而分配才是你问题的真正根源。我可以在引号中加上“change”或“modify”,但是的,我得到了这个事实。一个人可以单独使用self修改可变的类变量(因为引用),但我想知道(为了清楚起见)在处理类变量时,应始终使用类型(self).classvar(或classname.classvar)构造,并避免单独使用“self”的任何副作用。@MartyMacGyver:在某些情况下,
self