Mixins机制、元类简介、产生类的两种方式、元类的进阶操作、面向对象回顾

1 Mixins机制
2 元类简介
3 产生类的两种方式
4 元类的进阶操作
5 回顾面向对象

1 Mixins机制

class Vehicle:  # 交通工具
    pass


class FlyMinix():
    def fly(self):
        '''
        飞行功能相应的代码
        '''
        print("I am flying")


"""
1. 主类:就是大部分都是主要的功能
2. 辅类:就是一些辅助的功能
3. 辅类的类名也有讲究:一般以mixin、able、ible等结尾
4. 继承的位置也有讲究
"""


class CivilAircraft(FlyMinix, Vehicle):  # 民航飞机
    pass


class Helicopter(FlyMinix, Vehicle):  # 直升飞机
    pass


class Car(Vehicle):  # 汽车并不会飞,但按照上述继承关系,汽车也能飞了
    pass


import socketserver


2 元类简介

'''
什么是元类?
	即产生类的类
'''
"""type其实查看的是对象是有哪个类产生的!"""


class MyClass(object):
    pass


obj = MyClass()

# <class '__main__.MyClass'>
print(type(obj))  # 可以查看出obj对象是有哪个类产生的

"""你说我打印type(MyClass) 它的结果应该是什么呢?"""


# class type(object):
#     print(type(MyClass))  # <class 'type'>  我就可以认为MyClass类就是有type类产生的

class Student:
    pass


# print(type(Student)) # <class 'type'>


class C1():
    pass


print(type(C1))  # <class 'type'>
"""得出结论:我们之前使用class造出来的类都是由type类造出来的"""
"""我们说默认情况下,所有的类的元类就是type"""

3 产生类的两种方式

''' 
    1.class 类名():
        pass
    2.由于所有类都是有type类造出来的,所以我们也可以使用type类造出来一个新类
    type(object_or_name, bases, dict)
        这三个条件就是造出来类的三个要素.
        type("类名", "父类", "类的名称空间")
    3.为什么要学习元类?
'''  

"""
    元类是造出类的类,所以,我们可以对类进行高度的定制化.

    举个例子:
        我让你写出来的类名必须是首字母大写?

    思考:我们的定制化代码在哪里写呢?
        类是如何产生的?类是由元类产生的type类,如果想改类的行为,应该在元类里的__init__方法中改.

        对象是如何产生的? 是执行了产生这个对象的类内部的__init__方法

推导:已知推出来的未知.


注意:
    想改父类的__init__方法, 但是又不能修改源代码,所以我们可以写出来一个子类来继承父类type,
    在子类里面写代码,然后在从新执行一些父类的__init__方法.

"""


"""元类不能直接继承"""


class MyTypeClass(type):
    def __init__(self, cls_name, cls_bases=None, cls_dict=None):
        print(cls_name, cls_bases, cls_dict)  # C1 () {'__module__': '__main__', '__qualname__': 'C1'}
        # cls_name:它就是类名
        # 限制类名必须是首字母大写
        if not cls_name.istitle():
            raise Exception("类名必须是首字母大写")
        super().__init__(cls_name, cls_bases=None, cls_dict=None)


class C1(metaclass=MyTypeClass):
    school = 'Sh'


class a(metaclass=MyTypeClass):
    pass

4 元类的进阶操作

'''

__call__方法

对象加括号会自动调用类的__call__方法,并且,__call__方法里面返回什么,那么,对象加括号的位置就是什么

推导:类名()会怎么样?


"""类名(),应该是会执行产生类的类中的__call__方法,而这个类恰好是元类type"""
'''


class MyClass(type):
    def __call__(self, *args, **kwargs):
        print("__call__ 执行了")
        print(args, kwargs)

        """限制传参的方式必须是关键字传参,只需要args是空就行"""
        if args:
            raise Exception("传参必须是关键字传参")

        super(MyClass, self).__call__(*args, **kwargs)


class C1(metaclass=MyClass):
    def __init__(self, name):
        print("__init__ 执行了")
        # self.name = name


"""看C1类里面的__init__方法和元类里面的__call__方法的执行顺序"""
# 得出结论,其实在执行类的__init__之前,先执行了__call__方法

obj = C1(name='kevin')  # 都是位置传参,强制要求必须是关键字传参


5 回顾面向对象

面向过程

面向对象
	"""对象就是盛放数据属性和方法的容器"""
    
类的定义和对象的产生

class Student():
    school = 'SH'
    
    def index(self):
        pass
    
"""
定义类发生了什么事情:
	1. 一旦被定义,会立马执行类体代码
	2. 会产生类的名称空间,然后,把类中的名字丢到类的名称空间去,去就是放到字典里去了
	3. 把类的名称空间绑定给了__dict__属性, 类名.__dict__
"""

如何产生对象
	实例化,调用类,类名()

stu = Student() 默认实例化出来的对象是一个空对象,其实就是一个空字典
stu1 = Student()

print(stu.__dict__) # {}

定制对象自己独有的属性
方式1:
stu.__dict__['name'] = 'kevin'
stu.__dict__['age'] = '19'
stu.__dict__['gender'] = 'female'


方式2:
stu.name = 'kevin'
stu.age= '18'
stu.gender= 'male'


方式3def init(stu_obj, name, age, gender):
    stu_obj.name = name
    stu_obj.age = age
    stu_obj.gender = gender

init("kevin", 19, 'male')
init("kevin1", 29, 'female')

方式4class Student():
    school = 'SH'
    
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
    
    def index(self):
        pass
stu = Student("kevin", 19, 'male')  # Student(stu, "kevin", 19, 'male')
print(stu.name)
    

绑定方法和非绑定方法
绑定方法:
	1. 绑定给对象的
    	由对象来调用,特殊之处是会把对象自己当成第一个参数传给方法的第一个形参:self
        类也能来调用,只不过有几个参数就要传几个参数,一个不能少,一个也不能多,包括self
    2. 绑定给类的
    	先给方法的头上加一个装饰器:@classmethod, 方法的第一个形参就改成了cls
    	由类来调用,特殊之处是把类名当成一个参数传给方法的第一个形参:cls
非绑定方法:
	谁都不绑定
    先在方法的头上加一个装饰器:@staticmethod,加了这个装饰器之后,方法的self、cls都可以不要
    对象和类都可以来调用,就当成普通函数只有即可
隐藏属性
	 1、如何隐藏:在名字的前面加上__双下划线
     2、隐藏之后,名字会发生变形,_类名__属性名
     3、隐藏之后,在类的外部不能直接使用了,若非要使用也能用
     4、隐藏属性就是为了对外部进行更好的限制,在类的内部定义一个接口,然后返回隐藏的属性


property装饰器
	把方法伪装成属性来使用
	给方法名加装饰器
	1. property装饰器
	2. 方法名.setter
	3. 方法名.deleter

	另外一种方式:
	xxx = property('', '', '')
	
	'''这种方式是有顺序要求的'''
	例如:
    country = property(get_country, set_country, del_country)



继承:
	1. 继承就是新建类的一种方式,新建出来的类称之为子类,被继承的类称为是父类
    2. 子类可以遗传父类的属性和方法
    3. 继承解决的是类与类之间的代码冗余问题
    4. 继承的分类:
    	1. 经典类
        2. 新式类:就是继承object类的类
        """在python3中,都是新式类"""
继承下的属性查找:
	单继承下的
    	先从对象自己的名称空间查找,再去类中查找,最后在去继承的父类中查找
    多继承下的
    	菱形查找和非菱形查找
	        非菱形查找就是按照一个分支一个分支的查找
	        菱形查找
	        	经典类:深度优先查询,就是从第一个分支直接找到顶点
	            新式类:广度优先查询,就是从最后一个分支直接找到定点
        
        
 super和mro的使用
	super的使用是依赖继承的,它的查找顺序是遵循mro列表
    mro列表是一种c3算法的结果,每个类的mro列表不一样,但是需要从起始类开始

多态与多态性
	一种事物的多种形态
    抽象类:在父类中限制子类的行为,而不是异常父类的功能
    """方式1"""
    import abc
    class Animal(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def speak(self):
            pass
        
     class Dog(Animal):
        def speak(self):
            pass
    """方式2"""
	class Animal():
        def speak(self):
            raise Exception("")
        
     class Dog(Animal):
        def speak(self):
            pass
        
        
    class Dog():
        def speak(self):
            pass
        
     class Pig():
        def speak(self):
            pass
        
     class People():
        def speak(self):
            pass
	"""鸭子类型:更多的关注的是对象的行为,而不是对象的类型"""
    多态性:在不考虑对象的类型下,直接调用对象的方法
    举个多态的例子:len


组合:
	一个对象拥有一个属性,该属性的值是另外一个对象
魔术方法
	...
反射
	...
异常
	...
元类
	...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值