python中的类和self:实例和类变量
我是一个Python新手,完全被OOP和类中对python中的类和self:实例和类变量,python,python-3.x,class,oop,instance,Python,Python 3.x,Class,Oop,Instance,我是一个Python新手,完全被OOP和类中对self的需求搞糊涂了。我读过很多试图揭开谜团的帖子、博客等,但在这个特定场景中可能需要一些帮助 我是基于以下场景的。我将以我的例子开头,然后是下面明确的问题 首先,我将直接设置技巧,然后使用添加技巧方法: class Dog: tricks = [] def __init__(self, name): self.name = name def add_trick(self, trick):
self
的需求搞糊涂了。我读过很多试图揭开谜团的帖子、博客等,但在这个特定场景中可能需要一些帮助
我是基于以下场景的。我将以我的例子开头,然后是下面明确的问题
首先,我将直接设置技巧
,然后使用添加技巧
方法:
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
def print_self_tricks(self):
print(self.tricks)
a = Dog('spencer')
b = Dog('rex')
a.tricks = ['foo'] # How is this even possible? Where did I define self.tricks?
a.print_self_tricks()
['foo'] # Ok, the below results make sense
b.print_self_tricks()
[]
a.tricks
['foo']
b.tricks
[]
a.add_trick('jump')
a.print_self_tricks()
['foo', 'jump']
b.print_self_tricks()
[] # Great, as expected
a.tricks
['foo', 'jump']
b.tricks
[] # Great, as expected
现在,完全相同的设置,但执行顺序不同:add_trick
在直接设置trick
之前
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick)
def print_self_tricks(self):
print(self.tricks)
a = Dog('spencer')
b = Dog('rex')
a.add_trick('jump')
a.print_self_tricks()
['jump']
b.print_self_tricks()
['jump'] # Welp, that's not expected.
a.tricks
['jump']
b.tricks
['jump'] # Welp, that's not expected.
a.tricks = ['foo']
a.print_self_tricks()
['foo']
b.print_self_tricks()
['jump'] # Great, but inconsistent with the behavior above resulting from a.add_trick
a.tricks
['foo']
b.tricks
['jump'] # Great, but inconsistent with the behavior above resulting from a.add_trick
- 为什么存在自我欺骗?它从未在
中定义过(例如。 self.tricks=技巧)。我不认为这是可能的设置 self.tricks,因为它以前没有定义\uuuu init\uuuu
- 为什么我的方法没有得出不同的答案?也就是说,为什么
与a.tricks=['foo']
相比,似乎表现得像预期的那样李>a.add\u trick('roll over')
- 看来操作顺序很重要。为什么在设置.trick之前调用
会导致不同的结果添加\u trick
tricks
定义为类上的属性,而不是任何实例上的属性。类属性在某种意义上是在类的所有实例之间“共享”的。理想情况下,应该通过类访问它:Dog.tricks
,但Python也允许通过实例访问,例如a.tricks
或self.tricks
。规则是,如果x
是实例,x.y
将引用实例x
的属性y
(如果存在),否则x
的类的属性y
a.tricks = ['foo']
Python是一种动态类型化语言,不需要预先声明类、属性或变量。此语句在a
引用的Dog
实例上创建一个属性,并使其引用带有一个字符串的列表。在此之前,a.tricks
将解析为class属性所引用的仍然为空的列表,但在此之后,a.tricks
将解析为['foo']
<代码>技巧尚未设置为b
,因此b.tricks
仍然解析为与Dog.tricks
相同的内容
因此,您看到的行为是因为除非您显式地将a.tricks
设置为某物,a
和b
共享class属性。您可能并不打算这样做-尝试下面的方法,这将为每个实例提供自己的技巧:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []
这将tricks
定义为类上的属性,而不是任何实例上的属性。类属性在某种意义上是在类的所有实例之间“共享”的。理想情况下,应该通过类访问它:Dog.tricks
,但Python也允许通过实例访问,例如a.tricks
或self.tricks
。规则是,如果x
是实例,x.y
将引用实例x
的属性y
(如果存在),否则x
的类的属性y
a.tricks = ['foo']
Python是一种动态类型化语言,不需要预先声明类、属性或变量。此语句在a
引用的Dog
实例上创建一个属性,并使其引用带有一个字符串的列表。在此之前,a.tricks
将解析为class属性所引用的仍然为空的列表,但在此之后,a.tricks
将解析为['foo']
<代码>技巧
尚未设置为b
,因此b.tricks
仍然解析为与Dog.tricks
相同的内容
因此,您看到的行为是因为除非您显式地将a.tricks
设置为某物,a
和b
共享class属性。您可能并不打算这样做-尝试下面的方法,这将为每个实例提供自己的技巧:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []
“这怎么可能?我在哪里定义了self.tricks?”-就在那里,在那一行,在那项任务中。#这怎么可能?我在哪里定义了self.tricks?
就在这一行。但是你会感到困惑,因为你正在用一个实例变量来隐藏一个类级变量。tricks
在这种情况下,是一个跨Dog
s的所有实例共享的类变量“这怎么可能?我在哪里定义了self.tricks?”-就在这一行,这是怎么可能的?我在哪里定义了self.tricks?
就在这一行。但是您会感到困惑,因为您正在用实例变量来隐藏类级别变量。tricks
在本例中是一个跨Dog
s的所有实例共享的类变量