python面向对象答辩_python面向对象

面向对象思想

面向过程: 侧重在过程. 事物的发展流程

优点: 编码和入门简单.

缺点: 可扩展性差.

面向对象: 侧重在对象. 万事万物皆为对象.

优点: 可扩展性强(多态)

缺点: 上手难. 写起来麻烦

类与对象的关系

类是对事物的总结. 抽象的概念. 类⽤来描述对象. 对象是类的实例化的结果. 对象能执⾏哪些⽅法. 都由类来决定.

类中定义了什么.对象就拥有什么。

总结,在python中支持面向对象和面向过程. 使用哪一个你自己决定.python面向对象,一切皆为对象

面向对象三大特征

封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式。

封装原则

1. 将不需要对外提供的内容都隐藏起来

2. 把属性都隐藏,提供公共方法对其访问

实现

私有变量和私有方法,

在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式

不是真正的私有化,根于类名变形后,在类外面也可以访问到

封装与扩展性

只对外提供接口,修改内部的代码不影响外部调用者的代码

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口,只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

继承

子类继承父类. 子类会自动拥有父类中除了私有内容外的其他所有内容, python是多继承.

优点,代码复用。

继承与抽象

先抽象再继承,抽象即抽取类似或者说比较像的部分

继承原理

如何实现继承,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序表。

属性查找方法

子类会先于父类被检查

多个父类会根据他们在列表中的顺序被检查

如果下一个类存在两个合法的选择,优先选择第一个父类

多继承

经典类与新式类

在py2.2版本之前,只有经典类:经典类在基类的根如果什么都不写,表示继承XX

在py2.2版本之后,出现了新式类:新式类的特点是基类根是object

在py3版本中使用的都是新式类,默认继承object

MRO

py2.2之前,经典类,深度优先

py2.2,经典类,深度优先;新式类,列表去重,后因单调性问题,之后版本采用c3算法。

py2.3-py2.7,经典类,深度优先;新式类,C3算法

py3,C3算法,全部为新式类,默认继承object类(如果继承关系中没有菱形继承深度优先就够了)

C3算法

C3算法最早被提出是用于Lisp的,应用在Python中是为了解决原来基于深度优先搜索算法不满足本地优先级,和单调性的问题。

本地优先级:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。

单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。

基本上按照深度优先,但把多各类产生的共同继承的类最后去找。

可以通过类名.__mro__ 查看

算法

先拆分。 拆到你能看出结果为止. 反着进行merge()运算

合并 - 归并。merge(元组, 元组, 元组,...)

头和尾在比对,如果下一个尾没有这个头, 头就出现. 如果头在后面的尾出现.跳过该元组. 继续下一个头. 直到最后一个元组. 根自己匹配

ContractedBlock.gif

ExpandedBlockStart.gif

1 class A: pass

2 class B(A): pass

3 class C(A): pass

4 class D(B, C): pass

5 class E(C, A): pass

6 class F(D, E): pass

7 class G(E): pass

8 class H(G, F): pass

9

10 print(H.__mro__)11

12 #H的MRO

13 #H的MRO: ??

14 #拆

15 #L(H)= H + L(G) + L(F) -> H + (GECA) + (FDBECA) -> HGFDBECA (MRO)

16

17 #L(G) = G + L(E) -> G +(ECA) -> GECA

18 #L(F) = F + L(D) + L(E) -> F +(DBCA) + (ECA) -> FDBECA

19

20 #L(E) = E + L(C) + L(A) -> E + (CA) + A -> ECA

21 #L(D) = D + L(B)+ L(C) -> D + (BA) + (CA) -> DBCA

22

23 #L(c) = C + A CA

24 #L(B) = B + A BA

25

26 #L(A) = A

27

28 #合

29 #+ merge((B,), (A, ), 元组......) 算法

MRO

super()

super可以访问MRO列表中的下一个类中的内容. 找父类

ContractedBlock.gif

ExpandedBlockStart.gif

1 classPerson(object):2 def __init__(self, name):3 self.name =name4

5

6 classStudent(Person):7 def __init__(self, name, age):8 super(Student, self).__init__(name)9 self.age = age

super

ContractedBlock.gif

ExpandedBlockStart.gif

1 classPerson(object):2 def __init__(self, name):3 self.name =name4

5

6 classStudent(Person):7 def __init__(self, name, age):8 super(Student, self).__init__(name)9 self.age = age #MRO + super

10

11 classInit(object):12 def __init__(self, v):13 print("init")14 self.val =v15

16 classAdd2(Init):17 def __init__(self, val):18 print("Add2")19 super(Add2, self).__init__(val)20 print(self.val)21 self.val += 2

22

23 classMult(Init):24 def __init__(self, val):25 print("Mult")26 super(Mult, self).__init__(val)27 self.val *= 5

28

29 classHaHa(Init):30 def __init__(self, val):31 print("哈哈")32 super(HaHa, self).__init__(val)33 self.val /= 5

34

35 class Pro(Add2, Mult, HaHa): pass

36

37 classIncr(Pro):38 def __init__(self, val):39 super(Incr, self).__init__(val)40 self.val += 1

41 #Incr Pro Add2 Mult HaHa Init

42

43 #p = Incr(5)

44 #print(p.val)

45

46 #c = Add2(2)

47 #print(c.val)

48

49 #结论: 不不管super()写在哪⼉儿. 在哪⼉儿执⾏行行. ⼀一定先找到MRO列列表. 根据 MRO列列表的顺序往下找. 否则⼀一切都是错的

50 #super(Incr, self).__init__(val)

51 #在self的RMO表中Incr下一个类

MRO + super

组合

组合是指,在一个类中以另外一个类的对象作为数据类型,称为类的组合

1,继承的方式,是一种‘是’的关系,比如,人是动物,白马是马。

2,组合的方式,是一种‘有’的关系,比如,教授有生日,教授有学生。

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好。

接口,抽象类

接口

接口提取了一群类共同的函数,可以把接口当做一个函数的集合,然后让子类去实现接口中的函数。归一化。

实现,模仿java中的interface

2,使用继承

1,继承基类的方法,并且做出自己的改变或者扩展(代码重用)

2,声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能

ContractedBlock.gif

ExpandedBlockStart.gif

1 classInterface(object):2 defread(self):3 pass

4

5 defwrite(self):6 pass

7

8

9 classText(Interface):10 defread(self):11 print('文本读取数据的方法')12

13 defwrite(self):14 print('文本写入数据的方法')15

16

17 classSata(Interface):18 defread(self):19 print('硬盘读取数据的方法')20

21 defwrite(self):22 print('硬盘写入数据的方法')23 #上面代码看起来像接口,但根本没有起到接口的作用,子类可以不实现接口方法。

接口

抽象类

只能被继承,不能被实现。子类必须实现。借助模块实现。

抽象类是对类的抽象,抽取相同的内容而来。

ContractedBlock.gif

ExpandedBlockStart.gif

1 importabc2

3

4 class All_file(metaclass=abc.ABCMeta):5 all_type = 'file'

6

7 @abc.abstractmethod8 defread(self):9 pass

10

11 @abc.abstractmethod12 defwrite(self):13 #print(1)

14 pass

15

16

17 classTxt(All_file):18 defread(self):19 print('文本读取数据的方法')20

21 defwrite(self):22 print('文本写入数据的方法')23

24

25 classSata(All_file):26 defread(self):27 print('硬盘读取数据的方法')28

29 defwrite(self):30 print('硬盘写入数据的方法')31

32

33 if __name__ == '__main__':34 Txt().read()35 Sata().read()

抽象类

多态

一类事物有多种形态。

python天生支持多态,python没有多态的具体表现形式。

动物有多种形态:人,狗,猪

ContractedBlock.gif

ExpandedBlockStart.gif

1 importabc2

3

4 class Animal(metaclass=abc.ABCMeta): #同一类事物:动物

5 @abc.abstractmethod6 deftalk(self):7 pass

8

9

10 class People(Animal): #动物的形态之一:人

11 deftalk(self):12 print('say hello')13

14

15 class Dog(Animal): #动物的形态之二:狗

16 deftalk(self):17 print('say wangwang')18

19

20 class Pig(Animal): #动物的形态之三:猪

21 deftalk(self):22 print('say aoao')

多态

鸭子类型

当我看到一只鸟像鸭子一样游来游去,像鸭子一样游来游去,像鸭子一样呱呱叫,我就把那只鸟叫做鸭子。

我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。

不崇尚根据继承所得来的相似

如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型

list tuple 这种相似,是自己写代码的时候约束的,而不是通过父类约束的

优点:松耦合 每个相似的类之间都没有影响

缺点:太随意了,只能靠自觉

类的成员

变量

1. 实例变量(字段)

给对象用的。

2. 类变量(静态变量)

类变量,多个对象共享的,最好用类名访问,规范。

方法

1. 成员(实例)方法 加了self的.调用的时候。必须用对象去访问. (重点)

2. 类方法,类方法是将类本身作为对象进行操作的方法。类方法使用@classmethod装饰器定义,其第一个参数是类,约定写为cls。类对象和实例都可以调用类方法

使用场景:当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法

ContractedBlock.gif

ExpandedBlockStart.gif

1 classClassmethod_Demo():2 role = 'dog'

3

4 @classmethod5 deffunc(cls):6 print(cls.role)

classmethod

3. 静态方法,静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作。使用装饰器@staticmethod定义静态方法。类对象和实例都可以调用静态方法

使用场景:如果一个函数既和对象没有关系也和类没有关系那么就用staticmethod将这个函数变成一个静态方法

ContractedBlock.gif

ExpandedBlockStart.gif

1 classStaticmethod_Demo():2 role = 'dog'

3

4 @staticmethod5 deffunc():6 print("当普通方法用")7

8

9 Staticmethod_Demo.func()

staticmethod

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同。

属性

用方法来描述我们的属性信息.像访问变量一样访问方法。

注意:

1. @propery 改变一个方法成为属性

2. 这个方法只能有一个参数, self

3. 必须有返回值.

ContractedBlock.gif

ExpandedBlockStart.gif

1 #property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

2 importmath3

4

5 classCircle:6 def __init__(self, radius): #圆的半径radius

7 self.radius =radius8

9 @property10 defarea(self):11 return math.pi * self.radius ** 2 #计算面积

12

13 @property14 defperimeter(self):15 return 2 * math.pi * self.radius #计算周长

16

17

18 c = Circle(10)19 print(c.radius)20 print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值

21 print(c.perimeter) #同上

22 #c.area = 1 #不能给property方法赋值

property属性

私有

1. 私有变量,__变量

2. 私有方法,__方法

注意:私有化的只能由本类访问,对象不能访问,子类无法继承。

另外,python中是伪私有,可以用 obj._classname.__attrName 访问到。

ContractedBlock.gif

ExpandedBlockStart.gif

1 #类变量,类方法,成员方法,属性,静态方法

2 importtime3

4

5 classPerson:6 nationality = 'China' #类变量

7

8 def __init__(self, name=None, age=18):9 self.name =name10 self.age =age11

12 def eat(self): #成员方法

13 self.__class__.nationality = 'Germany' #在成员方法内访问类变量

14 print(self.__class__.nationality)15 print('in eat')16

17 @classmethod #类方法

18 defwalk(cls):19 cls.nationality = 'USA' #在类方法中访问类变量

20 print(cls.nationality)21 print('in walk')22

23 @staticmethod #静态方法,与类无关,只是在类里面而已

24 defsleep():25 print('in sleep')26

27 @property #属性

28 defbirthday(self):29 return int(time.strftime('%Y')) - self.age

类的成员示例代码

类与类的关系

世间万事的关系

1. 依赖关系,我用的到你,但你不属于我。

2. 关联关系,两种事物必须是互相关联的. 但是在某些特殊情况下是可以更改和更换的。

3. 组合关系,属于关联关系中的一种特例. 侧重点是xxx和xxx聚合成xxx. 各⾃有各⾃的生命周期.

4. 聚合关系,属于关联关系中的⼀种特例. 写法上差不多. 组合关系比聚合还要紧密.

5. 继承关系

6. 实现关系

python内部的主要关系

1. 依赖关系,在方法中传递参数.

2. 组合关系,self.xxx = xxxx

3. 继承关系,self,默认的self都是访问这个方法的对象.

类的特殊成员

类名()会自动执行 __init__()

对象()会自动执行 __call__()

对象[key] 会⾃动执⾏__getitem__()

对象[key] = value 会⾃动执⾏__setitem__()

del 对象[key] 会自动执⾏ __delitem__()

对象+对象 会⾃动执⾏ __add__()

with 对象 as 变量 会⾃动执⾏__enter__ 和__exit__

打印对象的时候 会自动执⾏ __str__

干掉可哈希 __hash__ == None 对象就不可哈希了了.

类名.__mro__ # 类的MRO(方法解析顺序)

类名.__name__# 类的名字(字符串)

类名.__doc__# 类的文档字符串

类名.__base__# 类的第一个父类

类名.__bases__# 类所有父类构成的元组

类名.__dict__# 类的字典属性

类名.__module__# 类定义所在的模块

类名.__class__# 实例对应的类(仅新式类中)

类名.__del__ # 析构方法,当对象在内存中被释放时,自动触发执行。

类名.__iter__ # 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__

类名.__new__ 类名.__metaclass__ # 创建并返回一个对象

创建对象的真正步骤

⾸先, 在执⾏类名()的时候. 系统会⾃动先执行__new__()来开辟内存. 此时新开辟出来的内存区域是空的. 紧随其后, 系统自动调⽤__init__()来完成对象的初始化⼯工作. 按照时间轴来算.

1. 加载类

2. 开辟内存(__new__)

3. 初始化(__init__)

4. 使⽤用对象⼲干xxxxxxxxx

反射

isinstance, type, issubclass

type()可以帮我们判断xxx是否是xxx数据类型的

isinstance()也可以判断xxx是yyy类型的数据. 还可以判断该对象是否是xxx家族体系中的(只能往上判断)

issubclass()这个内置函数可以帮我们判断XX类是否是YY类的子类

区分函数和方法

1. 类外面,都是定义的函数一定是函数

2. 类里面

类⽅法. 不论任何情况, 都是⽅法

静态⽅法, 不论任何情况. 都是函数

实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数。 对象.方法 方法 类名.方法 函数

用程序判断

# 用 FunctionType MethodType 判断

from types import MethodType, FunctionType

isinstance()

其实只要是与类绑定的都是方法,反之都是函数。

反射

仅限于内存层面,不会影响源代码

1. hasattr(obj, str) 判断对象中是否包含xxxx(str)

2. getattr(obj, str) 从对象中获取xxx(str)

3. setattr(obj, str, value) 把对象中的str设置成value

4. delattr(obj, str) 从对象中删除xxxx(str)

异常处理

异常(在程序运行中出现的错误),异常发生后,异常之后的代码不再执行。

异常处理,提高程序健壮性,出现异常,程序不会崩溃。

捕获异常

ContractedBlock.gif

ExpandedBlockStart.gif

1 #捕获异常

2 try:3 a = [1, 2]4 print(a[2])5 exceptIndexError as e:6 print(e)7 exceptKeyError as e:8 print(e)9 exceptException as e:10 print(e)11 else:12 print('try内代码块没有异常则执行我')13 finally:14 print('无论异常与否,都会执行该模块,通常是进行清理工作')15 #一般 try except 就够用了,最后再加个 finally 做收尾工

捕获异常

ContractedBlock.gif

ExpandedBlockStart.gif

1 #finally,else 与return

2 deff():3 try:4 a = [1, 2]5 #print(a[2])

6 print('in try')7 #return 'return_try'

8 exceptIndexError as e:9 print(e)10 print('in IndexError')11 return 'return_IndexError'

12 else:13 print('in else')14 return 'return_else'

15 finally:16 print('无论异常与否,都会执行该模块,通常是进行清理工作')17 print('in finally')18 return 'return_finally'

19

20

21 print(f())22 #总结

23 #“如果try中没有异常,那么except部分将跳过,执行else中的语句。(前提是try里没有返回值)

24 #finally是无论是否有异常,最后都要做的一些事情。”(无论try里是否有返回值)

25 #这里补充一句,在含有return的情况下,并不会阻碍finally的执行。(但是会阻碍else)

26 #不要在try else里写返回值。如果没有finally,就写在最后,或者只写在finally里。

27 #try except else里都是做某事 而不是处理返回

大坑 finally,else 与return

主动抛出

1 #主动触发异常

2 try:3 raise TypeError('类型错误')4 exceptException as e:5 print(e)

自定义异常

写个新类继承Exception,就OK

1 #自定义异常

2 classMyException(Exception):3 pass

4

5

6 try:7 raise MyException('哈哈哈,异常了')8 exceptMyException as e:9 print(e)

ContractedBlock.gif

ExpandedBlockStart.gif

1 importtraceback2

3 try:4 a = [12, 2]5 print(a[3])6

7 exceptIndexError as e:8 val = traceback.format_exc() #获取到堆栈信息

9 print(e)10 print(val)11 finally:12 print(233)

显示详细异常信息

断言

断言是用来检查非法情况而不是错误情况的,用来帮开发者快速定位问题的位置。

对一个函数而言,一般情况下,断言用于检查函数输入的合法性,要求输入满足一定的条件才能继续执行;

在函数执行过程中出现的异常情况使用异常来捕获

1 assert 1 == 1

2 assert 1 == 2

3 v1 = 1

4 v2 = 2

5 assert (v1 > v2), '{0} is not bigger than {1}'.format(v1, v2)

类的约束

约束是对子类进行的约束。

在python中有两种解决方案

1. 提取父类,然后在父类中定义好方法,在这个方法中什么都不用干,就抛一个异常(NotImplementError)就可以了,这样所有子类继承都必须重写次方法,否则报错。(推荐,python风格)

ContractedBlock.gif

ExpandedBlockStart.gif

1 classLogin:2 deflogin(self):3 raise NotImplementedError('没有实现login方法')4

5

6 classNormal(Login):7 #普通人登录

8 deflogin(self):9 pass

10

11

12 classMember(Login):13 #会员登录

14 defdenglu(self):15 pass

16

17

18 classAdmin(Login):19 #管理员登录

20 deflogin(self):21 pass

22

23

24 #项目经理的总入口

25 deflogin(obj):26 print('准备验证码')27 obj.login()28 print('进入主页')29

30

31 if __name__ == '__main__':32 login(Normal())33 login(Member()) #报错 NotImplementedError: 没有实现login方法

34 login(Admin())

提取父类

2. 使用元类来描述父类,在元类中给出一个抽象方法,这样子类就不得不实现此方法。

ContractedBlock.gif

ExpandedBlockStart.gif

1 from abc importABCMeta, abstractmethod2

3

4 class Login(metaclass=ABCMeta):5 @abstractmethod6 deflogin(self):7 pass

8

9

10 classNormal(Login):11 #普通人登录

12 deflogin(self):13 pass

14

15

16 classMember(Login):17 #会员登录

18 defdenglu(self):19 pass

20

21

22 classAdmin(Login):23 #管理员登录

24 deflogin(self):25 pass

26

27

28 #项目经理的总入口

29 deflogin(obj):30 print('准备验证码')31 obj.login()32 print('进入主页')33

34

35 if __name__ == '__main__':36 login(Normal())37 login(Member()) #报错 TypeError: Can't instantiate abstract class Member with abstract methods login

38 login(Admin())

元类描述

总结: 约束,其实就是父类对子类进行约束.子类必须要写xxx⽅法.在python中约束的方式和方法有两种:

1. 使用抽象类和抽象方法, 由于该⽅案来源是java和c#.所以使用频率还是很少的

2. 使用人为抛出异常的方案,并且尽量抛出的是NotImplementError. 这样比较专业, 而且错误比较明确.(推荐)

单例模式

单例模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

使用 __new__ 实现

1 classSingleton:2 def __new__(cls, *args, **kwargs):3 if not hasattr(cls, '_instance'):4 cls._instance = object.__new__(cls)5 returncls._instance6

7

8 one =Singleton()9 two =Singleton()10 #one和two完全相同,可以用id(), ==, is检测

11 print(id(one))12 #29097904

13 print(id(two))14 #29097904

15 print(one ==two)16 #True

17 print(one is two)

元类

参考

https://www.cnblogs.com/wupeiqi/p/4766801.html

https://www.cnblogs.com/kuaizifeng/p/9082181.html

阅读代码

1 class Foo: pass

2 obj = Foo #obj是通过Foo十实例化的对象

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类 本身也是一个对象,因为在Python中一切事物都是对象。

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

1 print(type(obj)) #输出: 表示,obj 对象由Foo类创建

2 print(type(Foo)) #输出: 表示,Foo类对象由 type 类创建

Python中的类的创建方式有两种

1,普通方式(通过class)

1 class Foo: pass

2 obj = Foo #obj是通过Foo十实例化的对象

2,特殊方式(type创建)

1 deffunc(self):2 print(233)3 Foo = type('Foo', (object,), {'func': func})4 Foo().func() #233

5 #type第一个参数:类名

6 #type第二个参数:当前类的基类

7 #type第三个参数:类的成员

元类的创建

ContractedBlock.gif

ExpandedBlockStart.gif

1 print("First...")2

3

4 classMyType(type):5 print("MyType begin ...")6

7 def __init__(self, *args, **kwargs):8 print("Mytype __init__", self, *args, **kwargs, sep="\r\n", end="\r\n\r\n")9 type.__init__(self, *args, **kwargs) #调用type.__init__

10

11 def __call__(self, *args, **kwargs):12 print("Mytype __call__", *args, **kwargs)13 obj = self.__new__(self) #第一个self是Foo,第二个self是F("Alex")

14 print("obj", obj, *args, **kwargs)15 print(self)16 self.__init__(obj, *args, **kwargs)17 returnobj18

19 def __new__(cls, *args, **kwargs):20 print("Mytype __new__", cls, *args, **kwargs, sep="\r\n", end="\r\n\r\n")21 return type.__new__(cls, *args, **kwargs)22

23 print("MyType end ...")24

25

26 print('Second...')27

28

29 class Foo(metaclass=MyType):30 print("begin...")31

32 def __init__(self, name):33 self.name =name34 print("Foo __init__")35

36 def __new__(cls, *args, **kwargs):37 print("Foo __new__", end="\r\n\r\n")38 return object.__new__(cls)39

40 print("over...")41

42 def __call__(self, *args, **kwargs):43 print("Foo __call__", self, *args, **kwargs, end="\r\n\r\n")44

45

46 print("third...")47 f = Foo("Alex")48 print("f", f, end="\r\n\r\n")49 f()50 print("fname", f.name)51

52 """

53 First...54 MyType begin ...55 MyType end ...56 Second...57 begin...58 over...59 Mytype __new__60 61 Foo62 ()63 {'__module__': '__main__', '__qualname__': 'Foo', '__init__': , '__new__': , '__call__': }64

65 Mytype __init__66 67 Foo68 ()69 {'__module__': '__main__', '__qualname__': 'Foo', '__init__': , '__new__': , '__call__': }70

71 third...72 Mytype __call__ Alex73 Foo __new__74

75 obj <__main__.Foo object at 0x10ae2ac88> Alex76 77 Foo __init__78 f <__main__.Foo object at 0x10ae2ac88>79

80 Foo __call__ <__main__.Foo object at 0x10ae2ac88>81

82 fname Alex83

84 """

元类的创建

解释一波

假设MyType是type类,type有三个特殊方法__init__、__call__、__new__。

首先, First请忽略掉吧。假设底层就这样搞了一个type类,它的名字叫MyType。

其次,Second这一步。解释器发现class和Foo(),会知道要从元类MyType中"实例化"一个类对象。

它会首先扫描class Foo()的整个上下文,并分成三部分,类名、基类元组,和私有字典。

然后它会告诉解释器,马上调用MyType(就是Type)类来创建一个名为Foo的类,来开辟内存空间,把这个Foo的私有字典(包括属性和方法)给放进去。

于是解释器执行了MyType.__new__,并继续执行MyType.__init__。来创建一个名为Foo的类对象。

再次,Third这一步。

首先通过Foo()来调用MyType.__call__,来实例化一个Foo类。它相当于Foo = Type()

然后依次执行Foo.__new__和Foo.__init__,来实例化一个实例对象。

Foo()相当于: MyType()(),而MyType()就是F。于是,在a = Foo(),实际上执行了MyType()()。前面说过,实例+()会调用所属类的__call__方法,同样地,类 + ()会调用类所属元类(MyType)的  __call__方法。

至此,一个实例就算创建完成了。

图示

1334917-20181024235344794-1591171819.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值