组合,Mixin,类、类对象、实例对象
1、组合,将几个横向关系的组合在一起。所谓的组合就是将类的实例化放到新类里面,那么就将旧类组合进去了。
class Turtle:
def __init__(self, x): # 注意 init 前面必须双下划线
self.num = x class Fish:
def __init__(self, x):
self.num = x class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x) # Pool类中实例化Turtle对象
self.fish = Fish(y) def print_num(self):
print('水池中共有乌龟 %d 只,小鱼 %d 条!'%(self.turtle.num,self.fish.num))
调用结果:
pool = Pool(2, 7)
>>> pool.print_num()
水池中共有乌龟 2 只,小鱼 7 条!
**:在新类中实例化旧类,如:self.turtle = Turtle(x) ,个人理解为将 Turtle 对象传递给 self.turtle 对象(属性),然后self.turtle 对象就具有Turtle 对象的属性了(体现在实例化 Pool 对象后,可以调用self.turtle.num,num 在 Pool 类中是没有定义的)。
2、Mixin 简介
Mixin 编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是有类的继承机制就可以实现,然而这与传统的类继承有所不同。通常 Mixin 并不作为任何类的基类,也不关心与什么类一起使用,而是在运行时动态的同其他零散的类一起组合使用。
特点
使用 Mixin 机制有如下好处:
- 可以在不修改任何源代码的情况下,对已有类进行扩展;
- 可以保证组件的划分;
- 可以根据需要,使用已有的功能进行组合,来实现“新”类;
- 很好的避免了类继承的局限性,因为新的业务需要可能就需要创建新的子类。
多继承
Python支持多继承,即一个类可以继承多个子类。可以利用该特性,可以方便的实现mixin继承。如下代码,类A,B分别表示不同的功能单元,C为A,B功能的组合,这样类C就拥有了类A, B的功能。
class A:
def get_a(self):
print 'a'
class B:
def get_b(self):
print 'b'
class C(A, B):
pass
c = C()
c.get_a()
c.get_b()
__bases__
多继承的实现就会创建新类,有时,我们在运行时,希望给类A添加类B的功能时,也可以利用python的元编程特性,__bases__属性便在运行时轻松给类A添加类B的特性,如下代码:
A.__bases__ += (B,)
a.get_b()
其实__bases__也是继承的机制,因为__bases__属性存储了类的基类。因此多继承的方法也可以这样实现:
class C:
pass
C.__bases__ += (A, B, )
插件方式
以上两种方式,都是基于多继承和python的元编程特性,然而在业务需求变化时,就需要新的功能组合,那么就需要重新修改A的基类,这回带来同步的问题,因为我们改的是类的特性,而不是对象的。因此以上修改会对所有引用该类的模块都收到影响,这是相当危险的。通常我们希望修改对象的行为,而不是修改类的。同样的我们可以利用__dict__来扩展对象的方法。
class PlugIn(object):
def __init__(self):
self._exported_methods = [] def plugin(self, owner):
for f in self._exported_methods:
owner.__dict__[f.__name__] = f
def plugout(self, owner):
for f in self._exported_methods:
del owner.__dict__[f.__name__]
class AFeature(PlugIn):
def __init__(self):
super(AFeature, self).__init__()
self._exported_methods.append(self.get_a_value)
def get_a_value(self):
print 'a feature.'
class BFeature(PlugIn):
def __init__(self):
super(BFeature, self).__init__()
self._exported_methods.append(self.get_b_value)
def get_b_value(self):
print 'b feature.'
class Combine:pass
c = Combine()
AFeature().plugin(c)
BFeature().plugin(c)
c.get_a_value()
c.get_b_value()
3、类、类对象、实例对象
class C:
count = 0 >>> a = C()
>>> b = C()
>>> c = C()
>>>a.count
0
>>> c.count += 10
>>> a.count
0
>>> b.count
0
>>> C.count += 100
>>> a.count
100
>>> b.count
100
>>> c.count
10
1)python中无处不对象。类中定义的属性时静态属性,类属性和类对象是绑定的,不依赖于实例对象。
2)实例化对象后,进行实例对象属性的修改不会影响类对象的属性,所以 c.count += 10不会影响 C.count 的值。
3)修改类对象属性属性之后,实例化对象的属性也会跟着改变,注意,经过实例对象修改过的属性不随着类属性的改变而改变(见上边染色部分代码),原因:个人理解为此处类似变量间的复制,实例对象是一个标签,和类对象指向同一个类属性地址,所以:a)类属性改变,实例对象属性跟着改变;b)单独修改实例对象属性是从新开辟堆栈,覆盖了该实例对象原本的类属性,所以这个修改不影响类属性,修改类属性也不影响经过修改的实例对象属性。
4、如果属性名称和方法名称一样,属性名称会覆盖方法名称。如下:给实例对象 c 定义 x 属性之后,再调用 x() 方法会报错。
4、绑定:Python 严格要求方法需要有实例才能够被调用,这种限制就是绑定概念。 个人理解:当实例对象调用方法时,会默认再方法里加一个 self 参数,如下面调用 bb.printBB()报错是因为 python默认的调用方式是 bb.printBB(bb),而 class BB 的printBB() 方法里面没有 self 参数,所以出现:TypeError :...but 1 was given 这个报错。
下面这段代码验证上面的个人理解。
class BB:
def printBB(self):
print('BB') >>> a = BB()
>>> a.printBB()
BB
>>> BB.printBB()
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
BB.printBB()
TypeError: printBB() missing 1 required positional argument: 'self'
>>> BB.printBB('b')
BB
5、查看对象属性:对象.__dict__
组合,Mixin,类、类对象、实例对象的更多相关文章
- PHP 简单面向对象 验证码类(静态实例对象调用)
没事写了一个简单的面向对象验证码类,可以直接使用(替换一下字体路径) <?php class authCode { private static $instance = null; #实例对象 ...
- Python高级语法-对象实例对象属性-类与实例,class方法静态方法等(4.6.1)
@ 目录 1.说明 2.代码 关于作者 1.说明 python中属性:类属性,实例属性 方法:类方法,实例方法,静态方法 想修改类属性,只能是类方法,因为只有类方法把cls(类)传入数据里面 静态方法 ...
- Java 同一个类的不同实例对象竟然可以相互访问各自的private成员
如题,在看String源码的某个函数时,发现了这个操作是被允许的,而且可以直接改变private字段(不是final按理是可以改变),这与之前的理解有点相背. 接下来试图整理下Google来的结论: ...
- Python高级语法-对象实例对象属性-Property总结(4.6.2)
@ 目录 1.说明 2.代码 关于作者 1.说明 property属性,返回的是值 不是callable的,也就是不能使用方法来调用 只能传入self,不能传入其他 用处,能返回局部数据,比如当分页的 ...
- Python - 面向对象编程 - 什么是 Python 类、类对象、实例对象
什么是对象和类 https://www.cnblogs.com/poloyy/p/15178423.html Python 类 类定义语法 最简单的类定义看起来像这样 class ClassName: ...
- python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法
类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实 ...
- js面向(基于)对象编程—类(原型对象)与对象
JS分三个部分: 1. ECMAScript标准--基础语法 2. DOM Document Object Model 文档对象模型 3. BOM Browser Object Moldel 浏览 ...
- Python类的特点 (2) :类属性与实例属性的关系
测试代码: #encoding:utf-8 class Parent(object): x=1 #x是Parent类的属性(字段) ls=[1,2] #ls是一个列表,也是Parent类的属性(字段) ...
- Python中的类属性、实例属性与类方法、静态方法
1.什么是类对象,实例对象 类对象:类名 实例对象:类创建的对象 2.类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++.Java中类的静态成员变量有点 ...
- Python3 之 类属性与实例属性
1.类属性与实例属性 类属性就相当与全局变量,实例对象共有的属性,实例对象的属性为实例对象自己私有. 类属性就是类对象(Tool)所拥有的属性,它被所有类对象的实例对象(实例方法)所共有,在内存中只存 ...
随机推荐
- YY的GCD
YY的GCD 给出T个询问,询问\(\sum_{i=1}^N\sum_{j=1}^M(gcd(i,j)\in prime)\),T = 10000,N, M <= 10000000. 解 显然质 ...
- github项目上传与克隆
1. 先去git官网https://git-scm.com/下载git: 2. 桌面新建文件夹,例如project,文件夹中新建任意文件例如index.html: 3. 打开文件夹,按住shift+右 ...
- x变成y的最少操作次数(层次遍历)
输入x,y,x为源数字,y为目标值.输出x变成y的最少操作次数. x每次可以执行三种操作:-1 . +1 . x2: 如 x=5,y=8:5-1=4,4x2=8;所以输出结果为2(次操作). 可以发现 ...
- 一道面试题引发对javascript事件循环机制(Event Loop)的 思考(这里讨论针对浏览器)
- WDA 新SELECT OPTION
感谢肖总的提示,不然还不知道wda的新select option... 使用前提:SE24类:CL_WDR_SELECT_OPTIONS_20 核对了多个版本,ERP系统版本要S4 1701往上,CR ...
- max of 直线划平面
在一个无限延伸平面上有一个圆和n条直线,这些直线中每一条都在一个圆内,并且同其他所有的直线相交,假设没有3条直线相交于一点,试问这些直线最多将圆分成多少区域. Input 第一行包含一个整数T,(0& ...
- 【IDEA填坑】xml不编译
今天在maven编译Springboot项目的时候,发现src/main/resources下的配置文件编译失败(就是war包中没有放入xml配置文件导致程序启动失败),经查询资料,发现新版本的IDE ...
- This application failed to start because it could not find or load the Qt platform plugin异常
双击项目Release文件夹下的exe程序无法启动: 解决办法: 1.将用到的QT组件拷贝到程序目录: 2.将D:\Qt\Qt5.3.2\5.3\msvc2013_64_opengl\plugins目 ...
- ELK快速部署及使用~
Elastic Stack 开发人员不能登陆线上服务器查看详细日志 各个系统都有日志,日志数据分散难以查找 日志数据量大,查询速度慢,或者数据不够实时 官网地址:https://www.elastic ...
- 简单的jQuery hide()方法演示
<!DOCTYPE html><html><head><meta charset="utf-8"> <title>jQu ...