【问题标题】:Why the Python scope seems to behave differently for list variable and string variable?为什么 Python 范围对于列表变量和字符串变量的行为似乎不同?
【发布时间】:2018-06-01 21:47:18
【问题描述】:

假设我有以下 Python 代码:

import sys

class DogStr:
    tricks = ''

    def add_trick(self, trick):
        self.tricks = trick

class DogList:
    tricks = []

    def add_trick(self, trick):
        self.tricks.append(trick)

# Dealing with DogStr
d = DogStr()
e = DogStr()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)

# Dealing with DogList
d = DogList()
e = DogList()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)

使用 Python 3.6.5 运行此代码,我得到以下输出:

trick d
trick e
['trick d', 'trick e']
['trick d', 'trick e']

DogStr 和 DogList 的区别在于,我将 tricks 视为前者的字符串,而将后者视为列表。

在处理 DogStr 时,tricks 表现为一个实例变量。但是使用 DogList 技巧的行为就像一个类变量。

我希望在两个调用中看到相同的行为,即:如果输出的最后两行相同,那么前两行应该是相同的。

所以我想知道。对此有何解释?

【问题讨论】:

  • 他们的行为并没有不同。如果您对列表执行self.tricks = trick,您将看到与字符串完全相同的行为。不同之处在于您正在做一些不同的事情——您正在改变列表值,而您并没有对字符串值做这件事(事实上,不能这样做,因为字符串是不可变的)。
  • 无论如何,这绝对是一个常见问题的重复,但我正在寻找最佳答案。同时,this onethis one 有一些有用的信息,即使它们不是重复的。
  • 我对 Python 缺乏经验。所以我不知道这是一个常见的问题。我找不到等效的问题,但感谢您指出相关问题。
  • 另见this onethis onethis one,但我现在放弃搜索;希望其他人找到副本。
  • 规则是您应该在发布之前搜索 dup……但是自动 dup 查找器没有用,而且,正如您所看到的,我很难为此找到 dup一个尽管很了解这里的 python 标签并且在过去找到了它,所以……我很难怪你找不到它。

标签: python python-3.x programming-languages


【解决方案1】:

区别不在于对象的类型,而在于你的代码对它做了什么。

这两者有很大区别:

self.tricks = trick

和:

self.tricks.append(trick)

第一个self.tricks = trickself 的属性tricks 赋值。

第二个self.tricks.append(trick) 检索self.tricks 并在其上调用一个方法(此处修改其值)。


在您的情况下,问题在于self 实例上没有定义tricks,因此self.tricks.append 获取类的tricks 属性并对其进行修改,但self.tricks = ... 创建了一个新属性改为self

其中一个是字符串,另一个是列表这一事实并不真正相关。如果两者都是列表,那将是相同的。 请注意,它们不能都是字符串,因为字符串是不可变的,因此没有附加方法

如何解决?

这是错误的:

def add_trick(self, trick):
    self.tricks = trick

如果tricks是类属性,add_trick应该是类方法:

@classmethod
def add_trick(cls, trick):
    cls.tricks = trick

如果有理由让add_trick 成为实例方法,那么只需这样做:

def add_trick(self, trick):
    DogStr.tricks = trick

【讨论】:

  • 初始化点,与范围有关,真的让我很困惑。感谢您解决此问题。
猜你喜欢
  • 2013-10-30
  • 1970-01-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 2017-10-25
  • 2022-01-14
  • 1970-01-01
  • 2015-06-18
相关资源
最近更新 更多