面向对象

1.元类介绍:
1.储备知识exec()
参数1;字符串形式得命令
参数2.全局作用域(字典形式),如果不指定默认就使用globals()
参数3.局部作用域(字典形式),如果不指定默认就使用locals()

2.python 一切皆对象 ,对象可以怎么用?
2.1. 都可以被引用 x=obj
2.2. 都可以当作函数得参数传入
2.3. 都可以当作函数得返回值
2.4. 都可以当作容器类得元素 li=[func,time]

# 类也是对象,Foo=type() 类是属于type() 类

3.什么叫元类
类得类就叫元类 type type(Foo) == <class 'type'>
产生类得类称之为元类,默认所有用class定义得类,他们得元类是type
元类(type) --> 实例化 --> 类(class)--> 实例化 --> 对象

4.定义类得两种方式:
4.1 class 关键字得方式 class Chinese:
4.2 type 元类 定义类得三要素:类名,类的基类们,类得名称空间
Chinese1=type(class_name,class_bases,class_dic)
 1 # print(globals())
 2 # print(locals())
 3 
 4 # g={
 5 #     'x':1,
 6 #     'y':2
 7 # }
 8 # l={}
 9 # exec("""
10 # global x,m
11 # x=10
12 # m=100
13 #
14 # z=3
15 # """,g,l)
16 # # print(g)
17 # print(l)
18 
19 # ----------------------------------------------------------
20 # 类也是对象,Foo=type()
21 # class Foo:
22 #     pass
23 #
24 # obj=Foo()
25 # print(type)
26 # print(type(Foo))
27 # print(type(obj))
28 
29 # class Bar:
30 #     pass
31 # print(type(Bar))
32 
33 # ----------------------------------------------------------
34 # 产生类得第一种方式: class
35 class Chinese:   # Chinese=type(...)
36     country='China'
37 
38     def __init__(self,name,age):
39         self.name=name
40         self.age=age
41 
42     def talk(self):
43         print('%s is talking'%self.name)
44 
45 
46 # print(Chinese)
47 obj=Chinese('alice',12)
48 print(obj,obj.name,obj.age)
49 
50 # 产生类得第二种方式: type
51 # 定义类得三要素:类名,类的基类们,类得名称空间
52 class_name='Chinese'
53 class_bases=(object,)
54 class_body="""
55 country='China'
56 
57 def __init__(self,name,age):
58     self.name=name
59     self.age=age
60 
61 def talk(self):
62     print('%s is talking'%self.name)
63 """
64 class_dic={}
65 exec(class_body,globals(),class_dic)
66 # print(class_dic)
67 
68 Chinese1=type(class_name,class_bases,class_dic)  # 实例化了元类 得到了一个 元类得对象
69 # print(Chinese.__dict__)
70 # print(Chinese1)
71 obj1=Chinese1('alice',18)
72 print(obj1,obj1.name,obj1.age)
2.自定义元类控制类的行为
自定义元类 来控制 类的行为 控制类的创建行为
 1 class Mymeta(type):
 2     def __init__(self,class_name,class_bases,class_dic):
 3         if not class_name.istitle():
 4             raise TypeError('类名的首字母必须大写')
 5         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
 6             raise TypeError('必须有注释,且注释不能为空!')
 7         print(class_name)
 8         print(class_bases)
 9         print(class_dic)
10         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
11 
12 
13 class Chinese(object,metaclass=Mymeta):
14     '''
15     中文人的类
16     '''
17     country='China'
18 
19     def __init__(self,name,age):
20         self.name=name
21         self.age=age
22 
23     def talk(self):
24         print('%s is talking'%self.name)
25 
26 # Chinese=Mymeta(class_name,class_bases,class_dir)
3.自定义元类控制类的实例化行为
知识储备 __call__方法
obj(1,2,3,a=1,b=2,c=3) # 对象在调用时 会触发 __call__
------------------------------------
#生成对象步骤 --》 #1.先造空对象 2.初始化 3.返回值
def __call__(self, *args, **kwargs): 在元类的__call__()方法中实现
# 1.先造一个空对象
obj=object.__new__(self)
# 2.初始化obj
self.__init__(obj,*args,**kwargs)
# 3.返回obj
return obj

总结:元类
__init__ 控制类的创建
__call__ 控制类的实例化
 1 # class Foo:  #(元类 ype )
 2 #     def __call__(self, *args, **kwargs):
 3 #         print(self)
 4 #         print(args)
 5 #         print(kwargs)
 6 # obj=Foo()
 7 # obj(1,2,3,a=1,b=2,c=3)  # 对象在调用时 会触发 __call__   #obj.__call__(obj,1,2,3,a=1,b=2,c=3)
 8 
 9 # 得出结论是:元类内部也应该有一个 __call__方法 会在调用Foo时触发执行
10 # Foo(1,2,x=1) 触发 # Foo.__call__(Foo,1,2,x=1) 控制类的调用
11 # 所以:元类里有__call__() 控制类的实例化(产生对象)
12 
13 # ----------------------------------------------------------
14 class Mymeta(type):                                                       #元类
15     def __init__(self,class_name,class_bases,class_dic):                  # 控制类的创建
16         if not class_name.istitle():
17             raise TypeError('类名的首字母必须大写')
18         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
19             raise TypeError('必须有注释,且注释不能为空!')
20         # print(class_name)
21         # print(class_bases)
22         # print(class_dic)
23         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
24 
25     def __call__(self, *args, **kwargs): #obj=Chinese('alice',age=18)      #控制类的实例化
26         # print(self)    # <class '__main__.Chinese'>
27         # print(args)    #('alice',)
28         # print(kwargs)  #{'age': 18}
29         # 1.先造一个空对象
30         obj=object.__new__(self)
31         # 2.初始化obj
32         self.__init__(obj,*args,**kwargs)
33         # 3.返回obj
34         return obj
35 
36 
37 class Chinese(object,metaclass=Mymeta):
38     '''
39     中文人的类
40     '''
41     country='China'
42 
43     def __init__(self,name,age):
44         self.name=name
45         self.age=age
46 
47     def talk(self):
48         print('%s is talking'%self.name)
49 
50 obj=Chinese('alice',age=18) # 触发Chinese.__call__(Chinese,'alice',18)
51 #生成对象步骤 --》 #1.先造空对象 2.初始化 3.返回值
52 print(obj.__dict__)
4.自定义元类控制类的实例化行为的应用
单例模式: 对象的参数都一样 实质就是一个对象 不要在申请新的内容空间 直接使用一个 就是单例模式
eg: 单例模式对id的应用 obj1 和 obj2 公用一块内存 “优化策略”
>>> obj1=int(1)
>>> obj2=int(1)
>>> obj1 is obj2
True
>>> id(obj1)
1897295328
>>> id(obj2)
1897295328
--------------------------------
自己定义的类 对象内部的特征如果是一样的就公用一块内存 用单例模式呢:
实现单例模式 是一种 优化策略 多个对象公用一块内存
__instance=None #__instance=obj1
def singleton(cls):
print(obj1 is obj2)
-------------------------------
单例模式的实现方式:1.@classmethod def singleton(cls):
2.利用元类实现
 1 # 单例模式:
 2 # 实现方式一:
 3 # class MySQL:
 4 #     __instance=None  #__instance=obj1
 5 #     def __init__(self):
 6 #         self.host='127.0.0.1'
 7 #         self.port=3306
 8 #
 9 #     @classmethod
10 #     def singleton(cls):
11 #         if not cls.__instance:
12 #             obj=cls()
13 #             cls.__instance=obj
14 #         return cls.__instance
15 #
16 #
17 #     def conn(self):
18 #         pass
19 #
20 #     def execute(self):
21 #         pass
22 #
23 # # obj1=MySQL()
24 # # obj2=MySQL()
25 # #
26 # # print(obj1)
27 # # print(obj2)
28 #
29 # obj1=MySQL.singleton()
30 # obj2=MySQL.singleton()
31 #
32 # print(obj1.host)
33 # print(obj2)
34 # print(obj1 is obj2)
35 
36 # --------------------------------------------------------
37 # 实现方式二:通过元类  实现了单例模式
38 class Mymeta(type):
39     def __init__(self,class_name,class_bases,class_dic):    #控制类的创建
40         if not class_name.istitle():
41             raise TypeError('类名的首字母必须大写')
42         if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
43             raise TypeError('必须有注释,且注释不能为空!')
44         super(Mymeta,self).__init__(class_name,class_bases,class_dic)
45         self.__instance=None
46 
47     def __call__(self, *args, **kwargs):   #控制类的实例化
48         if not self.__instance:
49             obj=object.__new__(self)
50             self.__init__(obj)
51             self.__instance=obj
52         return self.__instance
53 
54 
55 
56 class Mysql(object,metaclass=Mymeta):
57     '''
58     类的单例模式
59     '''
60     def __init__(self):
61         self.host='127.0.0.1'
62         self.port=3306
63 
64     def conn(self):
65         pass
66 
67     def execute(self):
68         pass
69 
70 obj1=Mysql()  # 在这个对象(Mysql)的类里面调用__call_()方法
71 obj2=Mysql()
72 obj3=Mysql()
73 
74 print(obj1 is obj2 is obj3)


原文地址:https://www.cnblogs.com/alice-bj/p/8541231.html