首页 > 其他 > 详细

第39讲:类和对象——拾遗/组合

时间:2020-08-15 22:58:56      阅读:84      评论:0      收藏:0      [点我收藏+]

一 组合的相关概念

 

1 组合:把类的实例化放在一个新类里面,就把旧类的内容组合到了新类里面

2 举例:

技术分享图片
 1 class Turtle(object):
 2     def __init__(self,x):
 3         self.num = x
 4     
 5 class Fish(object):
 6     def __init__(self,x):
 7         self.num = x
 8 
 9 class Pool(object):
10     def __init__(self,x,y):
11         self.turtle = Turtle(x)
12         self.fish = Fish(y)
13     
14     def print_num(self):
15         print(f"水池里面总共有乌龟{self.turtle.num}只,小鱼{self.fish.num}条!")
16 
17 pool = Pool(2,3)
18 pool.print_num()
class39.py

3 继承和组合的使用时机

  • “继承与组合”的问题可以归结为试图解决可复用代码的问题。
    • 继承通过在基类中创建隐含特性的机制来解决这个问题。
    • 组合通过提供模块以及调用其他类中的函数来解决这个问题
  • 怎么区分使用:
    • 无论如何都要避免多重继承,因为它太复杂而且不可靠。如果你被它困住了,那么要准备好了解一下类的层次结构,并花时间找出所有内容的来源。
    • 使用组合将代码打包到模块中,这些模块可以用于许多不同的、不相关的地方和情境。
    • 只有当存在明显相关的可复用代码片段,并且这些代码片段符合单个通用概念,或者由于你使用了某些东西而别无选择时,你才可以使用继承。
  • 关于面向对象编程,需要记住的一点是,它完全是程序员为了打包和共享代码而创建的一种社会约定。因为这是一种社会惯例,并且在 Python 中已经形成了这种惯例,你可能会因为与你一起工作的人而被迫绕过这些规则。在这种情况下,弄明白他们是如何使用每一种东西,然后努力适应这种情况。

二 类、类对象和实例对象

1 实例属性和类属性:

举例:

技术分享图片
 1 >>> class C(object):
 2 ...     count = 0
 3 ...
 4 >>> a = C()
 5 >>> b = C()
 6 >>> c = C()
 7 >>> a.count
 8 0
 9 >>> b.count
10 0
11 >>> c.count
12 0
13 >>> c.count += 10
14 >>> c.count
15 10
16 >>> a.count
17 0
18 >>> b.count
19 0
20 >>> C.count = 100
21 >>> a.count
22 100
23 >>> b.count
24 100
25 >>> c.count
26 10
class39.py

上述例子中:C是类对象,而a,b,c是实例对象。类属性(类中定义的变量)和类对象是相互绑定的,并不会依赖于实例对象。

即“c.count += 10” 只是改变了实例对象c对应的实例属性count的值(包括两个动作:创建一个实例属性,并给它赋值为10),并不会对跟类对象绑定的类属性count的值有任何影响;

而“C.count += 100”直接改变了类属性count的值,因为我们之前已经通过“c.count += 10”为实例对象c创建了一个新的实例属性,所以当我们再次执行c.count语句的时候调用的是实例对象C本身的实例属性,其值为10;而另外两个实例对象a,b并没有创建自己的实例属性(进行赋值操作),通过a.count和b.count其实相当于调用类本身的类属性count的值,所以输出为100.

技术分享图片

 

 2 属性跟方法

  • 举例:
    技术分享图片
     1 >>> class C(object):
     2 ...     def x(self):
     3 ...             print("X-man!")
     4 ...
     5 >>> c = C()
     6 >>> c.x()
     7 X-man!
     8 >>> c.x = 1
     9 >>> c.x
    10 1
    11 >>> c.x()
    12 Traceback (most recent call last):
    13   File "<stdin>", line 1, in <module>
    14 TypeError: int object is not callable
    class39_2.py
  • 常见错误:如果属性名跟方法名相同,属性会覆盖方法
  • 解决办法
    • 不要试图在一个类里面定义出所有能够想到的特性和方法,应该利用继承和组合机制来进行扩展。
    • 用不同的词性命名:如属性名用名词;方法名用动词

3 到底什么是绑定的概念?

  • 绑定:Python严格要求方法需要有实例才能被调用,这种限制其实就是python所谓的绑定的概念
  • 举例1 :
     1 >>> class BB(object):
     2 ...     def printBB():
     3 ...             print("no zuo no die")
     4 ...
     5 >>> BB.printBB()
     6 no zuo no die
     7 >>> bb = BB()
     8 >>> bb.printBB()
     9 Traceback (most recent call last):
    10   File "<stdin>", line 1, in <module>
    11 TypeError: printBB() takes 0 positional arguments but 1 was given

    这个例子中,定义printBB()的时候没有参数,后面通过类名(类对象)调用的时候可以正常打印,但是在为该类创建了一个实例对象bb之后,通过实例对象调用printBB()方法却没办法调用,所以说在定义printBB()方法的时候必须定义一个参数用来将实例名称传给该方法,这个过程即为绑定过程

  • 举例2:
     1 >>> class CC(object):
     2 ...     def setXY(self,x,y):
     3 ...             self.x = x
     4 ...             self.y = y
     5 ...     def printXY(self):
     6 ...             print(self.x,self.y)
     7 ...
     8 >>> dd = CC()
     9 >>> dd.__dict__
    10 {}
    11 >>> CC.__dict__
    12 mappingproxy({__module__: __main__, setXY: <function CC.setXY at 0x00000062CE34B670>, printXY: <function CC.printXY at 0x00000062CE34B700>, __dict__: <attribute __dict__ of CC objects>, __weakref__: <attribute __weakref__ of CC objects>, __doc__: None})
  • dd.__dict__ :实例对象的字典中仅有实例对象的属性,不显示类属性和特殊属性,就式没有显示哪些魔法方法(下划线包围的)
  • CC.__dict__:类对象的字典中全部显示,键表示属性名,值表示对应的值
  • 绑定的好处:
    • dd.__dict__:实例对象中没有显示类属性和类方法,也没有显示魔方方法(下划线包围)
    • CC.__dict__:类对象中全部显示了,键表示属性名/方法名,值表示键对应的值
    • 总结:相当于把类对象和实例对象完全分开了,之前定义的实例对象拥有独立于类对象存储空间之外的自己的存储空间
  • 举例3(补充2的内容):
     1 >>> dd.setXY(4,5)
     2 >>> dd.__dict__
     3 {x: 4, y: 5}
     4 >>> CC.__dict__
     5 mappingproxy({__module__: __main__, setXY: <function CC.setXY at 0x00000062CE34B670>, printXY: <function CC.printXY at 0x00000062CE34B700>, __dict__: <attribute __dict__ of CC objects>, __weakref__: <attribute __weakref__ of CC objects>, __doc__: None})
     6 >>> del CC
     7 >>> ee = CC()
     8 Traceback (most recent call last):
     9   File "<stdin>", line 1, in <module>
    10 NameError: name CC is not defined
    11 >>> dd.printXY()
    12 4 5
    • 1,2,3,4,5行:类对象的存储空间和实例对象的存储空间完全独立
    • 6,7,8,9,10,11行:类对象被删除,类对象的存储空间被销毁,但实例对象的存储空间仍旧存在,只有当程序退出之后,实例对象的存储空间才会被释放,相当于C语言中的静态变量
  • 总结:
    • 在大多数情况下,在编程中应该考虑使用实例属性,而不要去使用类属性;
    • 类属性通常使用来跟踪与类相关的一些值

有关继承和组合的内容,可参考:https://www.cnblogs.com/luoxun/p/13476773.html

有关类、类对象、实例对象的内容,可参考:https://www.cnblogs.com/luoxun/p/13411699.html

三 课后作业

 

第39讲:类和对象——拾遗/组合

原文:https://www.cnblogs.com/luoxun/p/13510118.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!