【问题标题】:Multiple values for same variable when designing Objects (use of self in Python)设计对象时同一变量的多个值(在 Python 中使用 self)
【发布时间】:2014-08-02 21:56:13
【问题描述】:

我是 python 新手(不是编程新手),我一直在搞乱“自我”的想法。我取得了长足的进步,但后来我发现搞乱我制作的一个小程序很有趣。我创建了一个名为 Person 的对象。这是我整个程序的代码。

class Person():
    name = "temp"
    def __init__(self, aname):
        global name
        print("A Person is created!")
        name=aname
        self.test()

    def test(self):
        print(name)
        print(self.name)

p1 = Person("Tim")

如您所见,我创建了一个名为“name”的变量。在构造函数中,我传入一个名为“aname”的变量并将其分配给变量“name”。在构造函数的末尾,我调用了一个名为 test 的方法,它打印出两件事。第一个实际上打印了我在构造函数中设置的名称(在本例中为“Tim”,如代码的最后一行所示),但第二个打印“temp”,这是我将“name”初始化为.价值观不应该一样吗?在我的场景中使用和不使用 self 有什么区别?

仅供参考,这是打印出来的,

创建了一个人!

提姆

温度

【问题讨论】:

  • 当您实例化多个Person 时,差异将变得明显。你会发现他们共享同一个name——也就是说,修改一个Person与修改所有Person是一样的。这可能不是你想要的。
  • 但是为什么 'name' 指向的值变成了 'Tim' 呢?为什么'self.name'会变成“temp”?值应该相同。
  • @WaleedKhan 的回答虽然准确地描述了创建多个 Person 对象时会发生什么,但在技术上是不正确的。设置为 Tim 的 name 不是您最初分配给 "temp"name - 它们属于两个不同的命名空间和范围。

标签: python variables python-3.x self


【解决方案1】:

您在init 中分配anamename 变量实际上与您最初声明为tmp 的变量不同——它是一个全新的全局变量。例如,您可以在代码末尾添加print name

class Person():
    name = "temp"
    def __init__(self, aname):
        global name
        print("A Person is created!")
        name=aname
        self.test()

    def test(self):
        print(name)
        print(self.name)

p1 = Person("Tim")
print name

你的输出将是:

A Person is created!
Tim
temp
Tim

另一种说明这一点的方法是完全更改变量的名称:

class Person():
    name = "temp"
    def __init__(self, aname):
        global asd
        print("A Person is created!")
        asd=aname
        self.test()

    def test(self):
        print(asd)
        print(self.name)

p1 = Person("Tim")

还会打印:

A Person is created!
Tim
temp

要完成我假设您希望完成的任务 - 即为每个人分配一个 name 属性,请使用 self.name 设置该属性。

class Person():
    name = "temp"
    def __init__(self, aname):
        print("A Person is created!")
        self.name=aname
        self.test()

    def test(self):
        print(self.name)

p1 = Person("Tim")

(请注意,在 test() 中尝试 print(name) 将失败,因为没有具有该名称的范围内属性。)

【讨论】:

  • 我来自 java,所以这可以解释我以下的困惑。我想让我感到困惑的是在 test() 中调用了“name”,它应该指向用“temp”初始化的初始名称。 'name' 在构造函数中调用时会突然变成全局变量吗?因为你可以在声明 'p1' 之后调用它,这确实令人困惑。
  • @gnasr:您不能像 Python 中那样隐式引用实例变量。如果您想要对象属性,则需要始终使用self.name。如果只使用name,它只能引用局部或全局变量,而不能引用对象的属性。
  • @BrenBarn:这是否意味着我在写“name=aname”时创建了全局变量。
  • @gnasr:是的,因为您声明了global name,就像 jmduke 在他的回答中解释的那样。 (如果你没有写global name,那么你只是创建了一个名为name的局部变量,它会在__init__完成后消失。)
  • @gnasr - 你是正确的,因为这种行为与 Java 不同。在 Java 中,类中的 self. 用法在很大程度上是可选的:仅当您将参数传递给与类属性同名的构造函数时才需要它——否则,它是可选的。在 Python 中,情况并非如此:您必须使用 self 引用对象的属性。
猜你喜欢
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-15
  • 2022-12-10
  • 2019-01-23
  • 2020-09-18
相关资源
最近更新 更多