Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的类和self:实例和类变量_Python_Python 3.x_Class_Oop_Instance - Fatal编程技术网

python中的类和self:实例和类变量

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):

我是一个Python新手,完全被OOP和类中对
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
  • 为什么存在自我欺骗?它从未在
    \uuuu init\uuuu
    中定义过(例如。 self.tricks=技巧)。我不认为这是可能的设置 self.tricks,因为它以前没有定义
  • 为什么我的方法没有得出不同的答案?也就是说,为什么
    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的所有实例共享的类变量