【问题标题】:Classes and self in python: instance and class variablespython中的类和self:实例和类变量
【发布时间】:2018-08-26 04:02:45
【问题描述】:

我是一个新手 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.add_trick('roll over') 相比,为什么a.tricks = ['foo'] 似乎表现得像预期的那样?
  • 似乎操作顺序很重要。为什么在设置 a.trick 之前调用 add_trick 会导致不同的结果?

*这是我目前读到的内容,还有更好的解释吗?

【问题讨论】:

  • “这怎么可能?我在哪里定义了 self.tricks?” - 就在那儿,在那条线上,带着那个任务。
  • # How is this even possible? Where did I define self.tricks? 从字面上看就在那一行。但是您会感到困惑,因为您正在使用实例变量来隐藏类级变量。
  • tricks 在这种情况下是一个在 Dogs 的所有实例之间共享的类变量

标签: python python-3.x class oop instance


【解决方案1】:
class Dog:
    tricks = []

这将tricks 定义为 上的属性,而不是任何实例 上的属性。类属性在某种意义上是在类的所有实例之间“共享”的。理想情况下,它应该通过类访问:Dog.tricks,但 Python 也允许通过实例访问,例如a.tricksself.tricks。规则是如果x是一个实例,x.y如果存在则引用实例x的属性y,否则引用x类的属性y

a.tricks = ['foo']

Python 是一种动态类型语言,不需要预先声明类、属性或变量。此语句创建Dog 实例上a 所引用的属性,并使其引用具有一个字符串的列表。在此之前,a.tricks 将解析为类属性所引用的仍然为空的列表,但在此之后,a.tricks 将解析为 ['foo']tricks 尚未在 b 上设置,因此 b.tricks 仍解析为与 Dog.tricks 相同的内容。

因此,您所看到的行为是因为在您将 a.tricks 明确设置为某物之前,ab共享类属性。您可能并不打算这样做 - 请尝试以下操作,这将为每个实例提供自己的 tricks

class Dog:
    def __init__(self, name):
        self.name = name
        self.tricks = []

【讨论】:

    猜你喜欢
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2013-08-16
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多