类 和 python 中的自我:实例和 class 变量
Classes and self in python: instance and class variables
我是一名新手 Python 程序员,对 OOP 和 类 中对 self
的需求感到非常困惑。我已经阅读了许多试图揭开它神秘面纱的 SO 帖子、博客* 等,但可以在这种特定情况下使用一些帮助。
下面的场景基于 Python2 tutorial on Class and Instance Variables。我将以我的例子开头,然后在下面提出明确的问题。
首先,我直接设置tricks
,然后使用add_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.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存在?它从未在
__init__
中定义(例如
self.tricks = 技巧)。我不希望它可以设置
self.tricks 因为之前没有定义它。
- 为什么我的方法没有得到不同的答案?也就是说,为什么
a.tricks = ['foo']
与 a.add_trick('roll over')
相比似乎表现得像预期的那样?
- 操作顺序似乎很重要。为什么在设置 a.trick 之前调用
add_trick
会导致不同的结果?
*这是我目前读到的内容,还有更好的解释吗?
class Dog:
tricks = []
这将 tricks
定义为 class 上的 属性,而不是任何 实例 . class 属性 在某种意义上是 "shared" 在 class 的所有实例之间。理想情况下应该通过 class: Dog.tricks
访问它,但是 Python 也允许通过实例访问,例如a.tricks
或 self.tricks
。规则是,如果x
是一个实例,x.y
将引用实例x
的属性y
(如果存在),否则y
的属性y
x
的 class.
a.tricks = ['foo']
Python 是一种 dynamically-typed 语言,不需要预先声明 class 元素、属性或变量。此语句 在 a
引用的 Dog
实例上创建 一个属性,并使其引用一个字符串列表。在此之前,a.tricks
将解析为 class 属性引用的 still-empty 列表,但在此之后,a.tricks
将解析为 ['foo']
。 tricks
尚未在 b
上设置,因此 b.tricks
仍解析为与 Dog.tricks
相同的内容。
所以你看到的行为是因为在你明确设置 a.tricks
之前,a
和 b
是 共享 class 属性。你可能不打算这样做 - 试试下面的方法,它会给每个实例自己的 tricks
:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []
我是一名新手 Python 程序员,对 OOP 和 类 中对 self
的需求感到非常困惑。我已经阅读了许多试图揭开它神秘面纱的 SO 帖子、博客* 等,但可以在这种特定情况下使用一些帮助。
下面的场景基于 Python2 tutorial on Class and Instance Variables。我将以我的例子开头,然后在下面提出明确的问题。
首先,我直接设置tricks
,然后使用add_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.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存在?它从未在
__init__
中定义(例如 self.tricks = 技巧)。我不希望它可以设置 self.tricks 因为之前没有定义它。 - 为什么我的方法没有得到不同的答案?也就是说,为什么
a.tricks = ['foo']
与a.add_trick('roll over')
相比似乎表现得像预期的那样? - 操作顺序似乎很重要。为什么在设置 a.trick 之前调用
add_trick
会导致不同的结果?
*这是我目前读到的内容,还有更好的解释吗?
class Dog:
tricks = []
这将 tricks
定义为 class 上的 属性,而不是任何 实例 . class 属性 在某种意义上是 "shared" 在 class 的所有实例之间。理想情况下应该通过 class: Dog.tricks
访问它,但是 Python 也允许通过实例访问,例如a.tricks
或 self.tricks
。规则是,如果x
是一个实例,x.y
将引用实例x
的属性y
(如果存在),否则y
的属性y
x
的 class.
a.tricks = ['foo']
Python 是一种 dynamically-typed 语言,不需要预先声明 class 元素、属性或变量。此语句 在 a
引用的 Dog
实例上创建 一个属性,并使其引用一个字符串列表。在此之前,a.tricks
将解析为 class 属性引用的 still-empty 列表,但在此之后,a.tricks
将解析为 ['foo']
。 tricks
尚未在 b
上设置,因此 b.tricks
仍解析为与 Dog.tricks
相同的内容。
所以你看到的行为是因为在你明确设置 a.tricks
之前,a
和 b
是 共享 class 属性。你可能不打算这样做 - 试试下面的方法,它会给每个实例自己的 tricks
:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []