self.属性在类中的作用域
本帖最后由 shatanzongcai 于 2020-7-29 21:51 编辑各位鱼油晚上好。我遇到了一个问题:
class People(object):
type = "human"
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
#info =
print(locals())
def __str__(self):
print(locals())
#print(info)
return f"这个人的名字是:{self.name},年龄是:{self.age},性别是:{self.gender}"
p = People("marry", 16, "female")
print(p)
暂时不看我注释掉的那两行,得出来的结果是:
>>>{'self': <__main__.People object at 0x00000286D0136400>, 'name': 'marry', 'age': 16, 'gender': 'female'}
>>>{'self': <__main__.People object at 0x00000286D0136400>}
>>>这个人的名字是:marry,年龄是:16,性别是:female也就是说self.属性即使是定义在一个方法中,也可以在另外一个方法(非静态方法和类方法)中调用,这么看来和type这个类属性的作用域是一样的。但是把注释的两行拿掉之后,就会报错,报错的原因是info没有定义。在这里info的作用域就限定在了__init__里面。
可是当我使用locals()的时候,我看到name,age,gender是在__init__方法里,它们并不存在在__str__方法里,为何__str__可调用呢?
而且当我在class的最后打印locals()
以上略
def __str__(self):
print(locals())
<font color="Red">#print(info)</font>
return f"这个人的名字是:{self.name},年龄是:{self.age},性别是:{self.gender}"
print(locals())
返回的是:
>>>{'__module__': '__main__', '__qualname__': 'People', 'type': 'human', '__init__': <function People.__init__ at 0x0000025ED3F5D700>, '__str__': <function People.__str__ at 0x0000025ED3E7F310>}
>>>{'self': <__main__.People object at 0x00000286D0136400>, 'name': 'marry', 'age': 16, 'gender': 'female'}
>>>{'self': <__main__.People object at 0x00000286D0136400>}
>>>这个人的名字是:marry,年龄是:16,性别是:female返回中并没有并没有出现name之类的。
所以self.属性的作用域是整个类的内部吗?为什么可以这样呀?
而且明明我把print(locals())写在类的最后,为什么反而它是第一个被打印出来的呢?
可是当我使用locals()的时候,我看到name,age,gender是在__init__方法里,它们并不存在在__str__方法里,为何__str__可调用呢?请见代码 4-6 行: self.name = name
self.age = age
self.gender = gender这里不是在给对象添加了属性吗?所以后面的return f"这个人的名字是:{self.name},年龄是:{self.age},性别是:{self.gender}"不会报错。 所以self.属性的作用域是整个类的内部吗?为什么可以这样呀?不是啊,在对象内部。 而且明明我把print(locals())写在类的最后,为什么反而它是第一个被打印出来的呢?因为 print(locals()) 是在类的定义时运行的,其余都是运行时打印的。 永恒的蓝色梦想 发表于 2020-7-29 21:54
请见代码 4-6 行:这里不是在给对象添加了属性吗?所以后面的不会报错。
为什么明明定义在另外一个方法中,__str__方法也可以调用得到呢,是说self.属性在对象里面有点类似于作用域最大变量吗,enclosing那样的? 永恒的蓝色梦想 发表于 2020-7-29 21:56
因为 print(locals()) 是在类的定义时运行的,其余都是运行时打印的。
好的,这个我试着跑了一下,确实是这样的,感谢 永恒的蓝色梦想 发表于 2020-7-29 21:55
不是啊,在对象内部。
这个是我写错了,我想说的就是在对象内部。为何它的作用域可以是整个对象内部呢 shatanzongcai 发表于 2020-7-29 22:06
为什么明明定义在另外一个方法中,__str__方法也可以调用得到呢,是说self.属性在对象里面有点类似于作用 ...
你给这个对象添加了属性,所以说可以访问啊。 shatanzongcai 发表于 2020-7-29 22:07
这个是我写错了,我想说的就是在对象内部。为何它的作用域可以是整个对象内部呢
你给对象赋值不是整个对象内部还能是啥呢? 本帖最后由 Stubborn 于 2020-7-29 22:12 编辑
locals() 函数会以字典类型返回当前位置的全部局部变量。
为什么类的属性(数据)成员驻留在实例命名空间,而类的方法成员驻留在类命名空间?理解这一问题是非常重要的。
当一个实例被构建好,类的属性(数据)成员就在`__init__`建立起来了。原始的赋值语句`self.args=0`,其中`self`是实例的标识符。在这种赋值中,`self.args`中的`self`作为限定符使用,这使得`args`标识符直接添加到实例命名空间。
而类的方法成员都是在类中声明的,所以它也与类命名空间中的自身命名相关连 下次这种4鱼币的悬赏不如发提问帖啦{:10_277:} 永恒的蓝色梦想 发表于 2020-7-29 22:11
下次这种4鱼币的悬赏不如发提问帖啦
不要鱼币,我们都是热心的程序猿 永恒的蓝色梦想 发表于 2020-7-29 22:11
你给对象赋值不是整个对象内部还能是啥呢?
我在上面使用了locals()来表示我的疑惑。self.name是在__init__被定义,我想问的是,它在__init__被定义之后,其他的方法为什么能够直接调用这儿self.name。而不是像普通的内嵌函数一样需要使用nonlocal之类的。是因为self.name被定义后,其实就好像是类属性的type一样吗?之所以我不能用最后的print(locals())打印出name之类的变量,是因为我没有实例化,所以打不出来吗? Stubborn 发表于 2020-7-29 22:11
locals() 函数会以字典类型返回当前位置的全部局部变量。
你说的实例命名空间是什么?是说实例的属性其实是放在实例的内存吗?这个我是知道的 永恒的蓝色梦想 发表于 2020-7-29 22:11
你给对象赋值不是整个对象内部还能是啥呢?
我看了很多帖子并没有人告诉我为什么是这样的,self.属性的作用域是整个对象这一点我写了一点代码验证了,但我其实想知道为什么。如果这个不重要的话我就不问了,以后还是直接拿来用。 shatanzongcai 发表于 2020-7-29 22:47
我看了很多帖子并没有人告诉我为什么是这样的,self.属性的作用域是整个对象这一点我写了一点代码验证了 ...
打个不太恰当的比喻:
你是一个人,你有两只手,这两只手不是你的还能是谁的? shatanzongcai 发表于 2020-7-29 22:28
我在上面使用了locals()来表示我的疑惑。self.name是在__init__被定义,我想问的是,它在__init__被定 ...
再次打个不太恰当的比喻。
你在储蓄罐里放了一元钱,你的妈妈把这一元钱取了出来。不都是可以得到这一元钱的么? 本帖最后由 Stubborn 于 2020-7-29 23:11 编辑
shatanzongcai 发表于 2020-7-29 22:33
你说的实例命名空间是什么?是说实例的属性其实是放在实例的内存吗?这个我是知道的
对呀,实例的属性其实是放在实例的内存。现在还有什么疑问的咩?
self.属性 -> `self`是实例的标识符。
比如 boj = Class() obj和 self 等同。
有时候你在类里面会见到sefl和cls
self 就表示实例的标识符 比如obj cls 就表示类的标识符 比如Class
Stubborn 发表于 2020-7-29 23:08
对呀,实例的属性其实是放在实例的内存。现在还有什么疑问的咩?
self.属性 -> `self`是实例的标识 ...
这个我知道了,locals()那个我再看看官方文档和其他帖子吧。谢谢! 本帖最后由 shatanzongcai 于 2020-7-30 00:09 编辑
永恒的蓝色梦想 发表于 2020-7-29 22:50
打个不太恰当的比喻:
你是一个人,你有两只手,这两只手不是你的还能是谁的?
你在重复一个我已经知道的事实,我知道self该怎么用,我想知道的是self背后的机制。比方说:
class People(object):
type = "human"
def func1(self):
self.data = 1
def func2(self):
print(self.data)
p = People()
p.func1()
p.func2()
self.data是在func1()里面定义的,为什么func2()里也可以使用。我知道它是可以这么用,但是我想知道为什么可以这么用。在普通的内嵌函数里,同样的形式不能访问得到,而在class里面有self的方法就可以做到。我问的是为什么人会长手而不是长翅膀,而不是手到底是不是长在我身上。如果你想说self就是这么用的,没有为什么,底层机制我不需要知道,那就当我没有发过这个贴,我直接把最佳给你就是了。
页:
[1]
2