首页 > 解决方案 > 关于实例的属性

问题描述

class Empl():
    def __init__(self, first, last):
        self.f = first
        self.l = last
        # Just checking something
        self.full = self.f + ' ' + self.l

first = Empl('Mickey', 'Mouse')

first.f = "Ricky"

print(first.full)  # It prints Mickey Mouse

为什么这种变化first.f没有反映在first.full?

标签: pythonpython-3.xoop

解决方案


self.fullname依赖self.fand self.l,使其成为属性

class Empl():
    def __init__(self, first, last):
        self.f = first
        self.l = last

    @property
    def fullname(self):
        return self.f + " " + self.l

现在,将使用andself.fullname的当前值即时计算 的值,而不是存储从(可能过时的)名字和姓氏创建的字符串。self.fself.l

请注意,您不能fullname直接更改,只能单独更改名字和姓氏。这是一个特点。(如何使fullname可分配超出了此答案的范围。)


该表达式self.f + ' ' + self.l未链接到self.for引用的对象self.l;以图形方式,您从

(1)
self.f ------>  "foo"
self.l ------>  "bar"

并以

(2)
self.f ------>  "foo"
self.l ------>  "bar"
self.full --->  "foo bar"

不像

(3)
self.f ------>  "foo"  <----\
                  " "  <----+---self.full
self.l ------>  "bar"  <----/

self.full是一个独立的对象,不受self.f或的变化的影响self.l


即使是上面的,也是一个小小的谎言。任何特定的 Python 实现都可能在三个字符串对象之间共享内存,因为str对象是不可变的。你不能改变实际strself.f引用来获得类似的东西

(4)
self.f ------>  "fpo"  <----\
                  " "  <----+---self.full
self.l ------>  "bar"  <----/

随着 的foo变化foo影响self.fself.full。您只能更改self.f所指的内容,例如

(5)
          +--> "fpo"
          |
self.f ---+     "foo"  <----\
                  " "  <----+---self.full
self.l ------>  "bar"  <----/

然而,任何这样的内存共享都只是一个实现细节,而不是 Python 本身可见的东西。实际上,您只能“看到”(2),字符串"foo"和是否"bar"在内存中表示一次或两次。


推荐阅读