QQ登录

只需一步,快速开始

开启左侧

Python学生第五十四天—类和对象3-绑定

[复制链接]
15271953841 发表于 2024-3-18 06:20:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
上接上一节课的内容
class Turtle:
    def say(self):
        print("不积跬步无以至千里~")

        
class Cat:
    def say(self):
        print("喵喵喵~")

        
class Dog:
    def say(self):
        print("呦吼,我是一只小狗~")

        
class Garden:
    t=Turtle()
    c=Cat()
    d=Dog()
    def say(self):
        t.say()         (省略前面的self.
        c.say()         (省略前面的self.
        d.say()         (省略前面的self.

        
g=Garden()
g.say()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    g.say()
  File "<pyshell#20>", line 6, in say
    t.say()
NameError: name 't' is not defined. Did you mean: 'self.t'?      (报错——提示“t”这个变量名并没有定义,why?  t=Turtle不是将t赋值给Turtle类的实例对象了吗?怎么说还没有定义?真是奇了怪了,想要弄清这个问题,就要知道这个self是干吗的,在学习类和对象第一节课时,这个self就是实例对象本身,当时的求证代码如下:
class C:
    def get_self(self):
        print(self)

        
c=C()
c.get_self()
<__main__.C object at 0x0000022BC9FEBD10>
c
<__main__.C object at 0x0000022BC9FEBD10>       (那么,这个self到底起到什么作用呢?绑定。就是实例对象跟类的方法绑定,因为类的实例对象可以有千千万,但是这些实例对象却是共享类里的方法,所以当我们在调用实例c.get_self的时候,其实际的含义是调用类C的get_self的方法,并把实例对象作为参数传递进去,进而实现绑定。所以类似的代码就是:
C.get_self(c)
<__main__.C object at 0x0000022BC9FEBD10>
大家都调用同一个方法,绑定来干吗呢?因为在实例中,除了类的方法是共享之外,实例的属性却是可以是自己的,例如:前面我们学习给实例对象添加属性,我们可以直接使用“.”号加上属性名称就可以:
d=C()
d.x=250
d.x
250
c.x
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    c.x
AttributeError: 'C' object has no attribute 'x'      (报错提示:这里没有找到x的属性,对象d的属性,对象c是访问不到的)
c.x=520         (给对象c也添加一个属性x)
c.x
520
d.x
250                  (可以看出c.x和d.x各是各的属性,互相不侵犯)
前面我们在学习函数的时候,提到过python是一门支持类型的编程语言,也就是说它的对象在运行的时候有自我观察的能力。那么这个对象,如果我们想要知道它当前拥有哪些属性,我们可以通过__dict__进行内省(dict左右都有两个下划线)
c.__dict__
{'x': 520}
d.__dict__
{'x': 250}
d.y=660
d.__dict__
{'x': 250, 'y': 660}
如果我们想通过类里的方法,来设置对象自己的属性,应该怎么做,方法是大家的,属性是自己的,通过self实现绑定。
class C:
    def set_x(self,v):
        self.x=v

        
c=C()
c.__dict__
{}                  (刚开始实例对象没有任何属性)
c.set_x(250)          (当我们调用了set_x这个方法后,并且随便传一个值)
c.__dict__            (这个时候我们再通过__dict__内省)
{'x': 250}              (里面多出了一个x的属性)
c.x
250                   (原来self.x=v这个操作就相当于c.x=v,因为self就是实例化对象本身,它俩已经通过self进行了一个绑定)
class C:
    x=100
    def set_x(self,v):
        x=v

        
c=C()
c.set_x(250)              (修改的是谁的值?)
c.x                      (显然不是对象小c的,因为我们把self去掉了)
100
如果修改对象的属性,必须通过self绑定才行,那会是修改类C(就是大C)的属性吗
C.x
100              (也不是,实际上,它谁也改不了,这个操作只是在set_x函数的内部创建了一个局部变量x,然后它的值把它赋值为250,它跟类和对象的x的属性都是没有关系的。)
C.x=250           (那现在如果我们现在通过类对其x属性进行修改)
c.x                (实例对象小c的x属性也会跟着变,因为此时对象小c自己是没有属性x的,这里能够访问到,是因为它由类C实例过来的,所以它也能访问到类C的属性。)
250
c.__dict__           (它是没有的,注意:对象中没有,不代表生成它的类没有,它的类没有不代表该类的父类没有,Python会一层一层往上去找,直到真的没有,才会引发异常)
{}
c.y
Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    c.y
AttributeError: 'C' object has no attribute 'y'
对于这种通过类来修改类属性的操作,不建议这么做,因为所有从这个类生成的实例对象都共享这个属性,如果直接修改,就会牵一发而动全身,导致多米诺骨牌效应。
二、一个旁门左道的小技巧
最小的类——当字典来使用
class C:
    pass
C.x=250
C.y="小姐姐"
C.z=[1,2,3]
print(C.x)
250
print(C.y)
小姐姐
print(C.z)               (类和对象的属性都是通过字典进行存放的)
[1, 2, 3]
d={}                    (使用字典的方式)
d["x"]=250
d["y"]="小姐姐"
d["z"]=[1,2,3]
print(d["x"])
250
print(d["y"])
小姐姐
print(d["z"])         (这样看出一样的效果,使用类来表示映射似乎还更方便一些,但是不要拿类来开涮,更常见的作法,是通过空类生成的实例来模拟字典,比如:
[1, 2, 3]
class C:
    pass
c=C()
SyntaxError: invalid syntax
c=C()
c.x=250
c.y="小姐姐"
c.z=[1,2,3]

归到上一节课开头,类和对象并不是必要的,因为几乎所有的实现,不使用面向对象编程,也能够实现,并且有时候代码执行的效率更高,面向对象的编程其实是一种高级的编程思想。

 楼主| 15271953841 发表于 2024-3-18 07:15:44 | 显示全部楼层
class C:
    x=100
    def set_x(self,v):
        x=v
        print("In,x=",x)
    print("out,x=",x)

   
out,x= 100
c=C()
c.set_x(250)
In,x= 250
c.x
100
C.x
100
客服热线
400-1234-888 周一至周日:09:00 - 21:00
公司地址:襄阳市樊城区长虹路现代城5号楼188

创客帮MAKER.BAND青少年创客创意社区是一个融教育、科技、体育资讯为一体的综合服务平台,专注于教育创新、专注于科技体育、专注于教育资讯。

Powered by Discuz! X3.4 © 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表