Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.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 作文:为什么是;“容器实例”;当“时,属性未更新”;“包含实例”;你变了吗?_Python_Class_Oop_Composition_Python Descriptors - Fatal编程技术网

Python 作文:为什么是;“容器实例”;当“时,属性未更新”;“包含实例”;你变了吗?

Python 作文:为什么是;“容器实例”;当“时,属性未更新”;“包含实例”;你变了吗?,python,class,oop,composition,python-descriptors,Python,Class,Oop,Composition,Python Descriptors,我想更好地理解容器对象属性和包含对象属性之间的关系 我想了解这个示例的输出: 我创建了一辆高级轿车和一个高级轮胎。 Tire还有一个属性age,应该“指向”名为bmw的汽车实例的属性。 因此,我认为通过更改bmw实例的属性,倍耐力属性age也应该更新,因为它引用了相同的变量。从示例中可以看出,情况并非如此 我怎样才能真正更新它呢? 我计划多次使用作文,所以在最后一节课上使用它是非常不切实际的 finalInstance.age=先前的instances.tire.car.age class Ca

我想更好地理解容器对象属性和包含对象属性之间的关系

我想了解这个示例的输出:

我创建了一辆高级轿车和一个高级轮胎。
Tire还有一个属性age,应该“指向”名为bmw的汽车实例的属性。 因此,我认为通过更改bmw实例的属性,倍耐力属性age也应该更新,因为它引用了相同的变量。从示例中可以看出,情况并非如此

我怎样才能真正更新它呢? 我计划多次使用作文,所以在最后一节课上使用它是非常不切实际的

finalInstance.age=先前的instances.tire.car.age

class Car:
    def __init__(self, age):
        self.age = age

class Tire:
    def __init__(self, car):
        self.car = car
        self.age = self.car.age

bmw = Car(age=1)
print('Car age is ',bmw.age)

pirelli = Tire(car=bmw)
print('Tire age is ',pirelli.age)

bmw.age = 2
print('Car age is now ',bmw.age)
print('Tire age is now ',pirelli.age)
我希望这一产出:

Car age is  1
Tire age is  1
Car age is now  2
Tire age is now  2
但我得到的是:

Car age is  1
Tire age is  1
Car age is now  2
Tire age is now  1
谁能帮我找到一种方法让self.age=self.car.age自动更新轮胎


多谢各位

可能更适合设计一款
级车,它有
轮胎
,而不是相反

在这种情况下,使用属性getter和属性setter,您可以将汽车年龄的变化与其轮胎的老化耦合起来

大概是这样的:

class Car:
    def __init__(self, age, tire):
        self._age = age
        self.tire = tire
    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        delta = age - self.age
        self._age += delta
        self.tire.age += delta

class Tire:
    def __init__(self, age=1):
        self.age = age

pirelli = Tire()
bmw = Car(1, pirelli)
print('Car age is ',bmw.age)


bmw.age = 2
print('Car age is now ',bmw.age)
print('Tire age is now ',pirelli.age)
输出:

Car age is  1
Car age is now  2
Tire age is now  2

Python中的赋值操作符
=
确实更改了指定给该对象的名称所指向的对象

换句话说,在您的示例中,行
self.age=self.car.age
指向运行该行时在
self.car
中定义的数字(对象)。当您稍后运行
bmw.age=2
以更改car类中的属性时,它将指向一个新对象。但是
bmw.car.age
没有改变

您必须首先很好地理解这一点,并且简单明了的方法就是使用属性
self.car.age
的完整路径,即使在
Tire
类中也是如此

然后,如果您真的认为需要动态更改属性,我们必须求助于“反应式”编程—一种方法,其中状态中的一个更改自动传播到代码中的其他位置。Python允许以多种方式实现这一点。下面是一个例子

因此,Python必须处理这类事情的强大机制之一是“”——该语言指定,如果对象绑定为类属性——也就是说,在
主体中定义,而不仅仅是在
\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu或其他方法中定义——则具有
\uuu get\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu(或两个其他特殊命名方法),检索或尝试重新绑定(使用
=
)该类实例中的该属性将通过该类中的该对象。该对象称为“描述符”

Python的
属性
decorator使用这种机制来提供为属性创建setter和getter的最常用案例。但是,由于您需要对许多类似属性使用相同的访问和获取规则,因此创建一个专门的描述符类更为合理,它将“知道”属性的源,并始终转到其源以获取或设置其值

下面的代码以及“汽车、轮胎和螺钉”类提供了一个示例:

类链接属性:
定义初始化(自身,容器路径):
self.container\u path=容器路径
定义设置名称(自身、所有者、名称):
self.name=名称
def_get_容器(自身,实例):
容器=实例
对于self.container_path.split(“.”)中的组件:
container=getattr(容器、组件)
返回容器
定义获取(自身、实例、所有者):
如果实例为“无”:
回归自我
container=self.\u get\u container(实例)
返回getattr(容器,self.name)
定义集(自身、实例、值):
container=self.\u get\u container(实例)
setattr(容器、self.name、值)
等级车:
定义初始(自我、年龄):
self.age=年龄
轮胎等级:
年龄=LinkedAttribute(“汽车”)
定义初始(自我,汽车):
self.car=汽车
self.age=self.car.age
等级螺钉:
年龄=链接属性(“轮胎、汽车”)
def u u初始(自身,轮胎):
self.tire=轮胎
在交互式口译员中,我们有:

[37]中的
:宝马=汽车(2)
...:                                                                                     
In[38]:t1=轮胎(宝马)
...:                                                                                     
In[39]:s1=螺钉(t1)
In[40]:t1.age
Out[40]:2
In[41]:bmw.age=5
In[42]:t1.age
Out[42]:5
In[43]:s1.年龄
Out[43]:5
在[44]中:s1.age=10
在[45]中:bmw.age
Out[45]:10

当然,如果您不想允许从包含的类修改父类的任何属性,只需省去(或放置一个保护标志)在
\uuuu set\uuuu
方法上。

是否可以将类结构保留为OP?a
轮胎
,它有一辆
汽车
,不知道它的
轮胎
…是的,可以通过
发布者
订阅者
:一个轮胎将向它的汽车注册,以监听汽车年龄的变化,并在发布
car.age
change时自行调整……这会让人感觉很轻松