第046讲:魔法方法:描述符(Property的原理)中的疑问
在46讲的习题中,小甲鱼给出的代码是:import time
class Record:
def __init__(self, initval=None, name=None):
self.val = initval
self.name = name
self.filename = "record.txt"
def __get__(self, instance, owner):
with open(self.filename, 'a', encoding='utf-8') as f:
f.write("%s 变量于北京时间 %s 被读取,%s = %s\n" % \
(self.name, time.ctime(), self.name, str(self.val)))
return self.val
def __set__(self, instance, value):
filename = "%s_record.txt" % self.name
with open(self.filename, 'a', encoding='utf-8') as f:
f.write("%s 变量于北京时间 %s 被修改, %s = %s\n" % \
(self.name, time.ctime(), self.name, str(value)))
self.val = value
有如下一些疑惑:
1. 在运行的时候,是不是也要也要设置某个类,其中该类的有个属性是Record类,也就是
class C:
x=Record()
2.filename = "%s_record.txt" % self.name这个语句有什么用?
3.如果:
c=C()
c.x=8
d=C()
那问什么d.x也是8呢?
4. Record类中的初始化是不是只是在
Class C:
x=Record()
的时候被调用。这样的话,3中的c,d实际上就不能被赋予不同的初始化值。我写这样的代码
class E:
def __init__(self,init=None,name=None):
self.x=Record(init,name)
然后e=E(100,'china'),那为什么e.x返回的只是对象的地址,而e.x.val才能够返回100.谢谢
1,x = Record(), 是类的实例化,x是Record类的实例化对象,如果要使用类的方法,使用类的继承即可
2,filename = 说明是文件名, 这个语句就是设置一个文件名
3,c = C(), c是一个实例化对象,c.x是给这个对象一个属性赋值, d = C(), d是一个实例化对象,虽然继承同一个父类,但是是两个毫不相干的对象
4,class C:/x = Record() 只是在类中实例化一个对象,而不是,x这个实例化对象作为C这个类的属性
而很明显,下面e.x这个是e的属性,这个属性是一个对象,而要查看一个对象的属性,需要e.x.val
另外,类的初始化在类被调用一开始进行,但是不是最开始,最开始被调用另有它人(忘了,你后面会学到)
HZX0229 发表于 2021-2-25 20:24
1,x = Record(), 是类的实例化,x是Record类的实例化对象,如果要使用类的方法,使用类的继承即可
2,fil ...
谢谢,您的回答。还是有些问题:
第2个问题我的意思是这个语句实际上在整个代码中没用啊?
第3个问题如果c=C()\c.x=8\d=C()之后,如果c,d是两个不相关的实例对象,那为什么d.x也是8呢? Tshirt 发表于 2021-2-25 21:03
谢谢,您的回答。还是有些问题:
第2个问题我的意思是这个语句实际上在整个代码中没用啊?
第3个问题如 ...
2, 没用到要么这上面的代码错了,检查一下代码, 要么这个习题上这句代码就是多余的
3,d.x = 8, 那么C这个类里面x这个属性就是8 HZX0229 发表于 2021-2-25 21:37
2, 没用到要么这上面的代码错了,检查一下代码, 要么这个习题上这句代码就是多余的
3,d.x = 8, 那么 ...
谢谢您的回答,对于第三个问题我还是有点困惑。我的理解是有个类C,,c,d都是类C的实例对象,他们都有一个属性x,而该属性是类Record的实例对象。设置c的属性x,为什么会影响到d的属性x呢?谢谢 本帖最后由 HZX0229 于 2021-2-27 09:12 编辑
Tshirt 发表于 2021-2-27 08:15
谢谢您的回答,对于第三个问题我还是有点困惑。我的理解是有个类C,,c,d都是类C的实例对象,他们都有一个 ...
类好比一个人群, 属性就是这个人群的一个特征,实例化一个人群就好比是从这个人群中选出一个人,这个人就是一个实例化对象,设置一个人的属性不会影响到人群,而设置一个人群中的属性,会影响这个人群中的所有人,设置c.x 并不会影响到 d.x,除非设置C.x。
class C:/ def __init__(self):/ self.x = 0/ c = C()/ c.x = 8/ d = C()/ print(d.x)
上面这行代码方便你理解 HZX0229 发表于 2021-2-27 09:07
类好比一个人群, 属性就是这个人群的一个特征,实例化一个人群就好比是从这个人群中选出一个人,这个 ...
感谢您的回复。您举得例子我能够理解。我的问题是在代码
import time
class Record:
def __init__(self, initval=None, name=None):
self.val = initval
self.name = name
self.filename = "record.txt"
def __get__(self, instance, owner):
with open(self.filename, 'a', encoding='utf-8') as f:
f.write("%s 变量于北京时间 %s 被读取,%s = %s\n" % \
(self.name, time.ctime(), self.name, str(self.val)))
return self.val
def __set__(self, instance, value):
filename = "%s_record.txt" % self.name
with open(self.filename, 'a', encoding='utf-8') as f:
f.write("%s 变量于北京时间 %s 被修改, %s = %s\n" % \
(self.name, time.ctime(), self.name, str(value)))
self.val = value
class C:
x=Record()
c=C()
c.x=8
d=C()
后,为什么d.x也是8呢?我的理解是c,d是C的实例化对象,每个对象都有一个x属性,该属性又是一个Record类的实例化对象,但为什么c.x和d.x这两个实例化对象会一样呢?谢谢 Tshirt 发表于 2021-2-27 10:55
感谢您的回复。您举得例子我能够理解。我的问题是在代码
import time
我第一次回复就说了,x是一个实例化对象,这里x不作为实例化对象c的一个特有属性,而是作为一个共有属性,相当于类C里面的常量,既然是共有的,那就可以通过c.x修改,可以影响到类C里面的x,self就是起到一个限制的作用,self.~这个属性是这个对象特有的, HZX0229 发表于 2021-2-27 11:13
我第一次回复就说了,x是一个实例化对象,这里x不作为实例化对象c的一个特有属性,而是作为一个共有属性 ...
对不起耽误您时间了,“x是一个实例化对象,这里x不作为实例化对象c的一个特有属性,而是作为一个共有属性”这个我没问题,就像你前面举得例子class C:/ def __init__(self):/ self.x = 0/ c = C()/ c.x = 8/ d = C()/ print(d.x),类C的每个实例化对象都有x这个属性,例如c,d都有这个属性,但您后面说的“相当于类C里面的常量”我就不能理解了,就像您这个例子class C:/ def __init__(self):/ self.x = 0/ c = C()/ c.x = 8/ d = C()/ print(d.x)中,c.x和d.x可以不一样啊? Tshirt 发表于 2021-2-27 12:00
对不起耽误您时间了,“x是一个实例化对象,这里x不作为实例化对象c的一个特有属性,而是作为一个共有属 ...
关键在Record 这个类, 它有两个魔法方法, c.x = 8 它调用了__set__方法,把self.val 设置为8, d.x 这里又调用了__get__方法, 返回了self.val, 差点把我自己绕进去{:5_104:} HZX0229 发表于 2021-2-27 13:41
关键在Record 这个类, 它有两个魔法方法, c.x = 8 它调用了__set__方法,把self.val 设置为8, d.x 这 ...
谢谢,那么c.x=8中调用了__set__方法,把self.val 设置为8, d.x 这里又调用了__get__方法, 返回了self.val, 这两个self是一样的?我原来觉得是c.x=8中__set__是把c.x这个Record对象中的val属性设置为8,d.x是通过__get__方法获得d.x这个Record对象中的va属性,但是d没有设置过,应该就是初始化值。这样理解为什么不对呢?
谢谢
Tshirt 发表于 2021-2-27 15:31
谢谢,那么c.x=8中调用了__set__方法,把self.val 设置为8, d.x 这里又调用了__get__方法, 返回了self. ...
c.x and d.x 是同一个对象,即x , 它们返回的都是x.val HZX0229 发表于 2021-2-27 19:06
c.x and d.x 是同一个对象,即x , 它们返回的都是x.val
好的,谢谢您
class Attr:
def __init__(self, key, type_):
self.key = key
self.type_ = type_
def __set__(self, instance, value):
print('in __set__')
if not isinstance(value, self.type_):
raise TypeError('must be %s' % self.type_)
instance.__dict__ = value
def __get__(self, instance, cls):
print('in __get__', instance, cls)
return instance.__dict__
def __delete__(self, instance):
print('in __del__', instance)
del instance.__dict__
class Person:
name = Attr('name', str)
age = Attr('age', int)
p = Person()
p.name = 'tom'
#p.age = 20
p.age = '20'
找个一个比较好的解决方式,在set方法中用instance.__dict__
页:
[1]