Python--面向对象进阶

一、元类
元类是类的类,是类的模板;元类的实例为类,正如类的实例为对象。类也是对象。
在这里插入图片描述
类的本质是对象, 于是可以对类做如下的操作:

  1. 你可以将它赋值给一个变量
  2. 你可以拷⻉它
  3. 你可以为它增加属性
  4. 你可以将它作为函数参数进行传递

因为类也是对象,运行时在函数中使用class关键字动态的创建类。

1、通过分支语句动态的创建类

def create_class(name):
    if name == 'foo':
        class Foo(object):
            pass
        return  Foo
    else:
        class Bar(object):
            pass
        return  Bar

cls = create_class(name='foo1')
print(cls.__name__)
Bar

2、通过type函数动态创建类
type函数功能一: 判断对象的类型。
type函数功能二: 动态的创建类。type可以接受一个类的描述作为参数,然后返回一个类。
type函数语法: type(类名,父类名称的元组, 属性信息)

def hello(self):
    print("hello")
Person = type('Person',(object, ), {'country':'China', 'hello':hello})
p1 = Person()
print(p1.country)
p1.hello()
China
hello

什么是元类?
1). 元类就是创建类的类。函数type就是是元类。
2). Python中一切皆对象。包括整数、字符串、函数以及类都是对象,且都是从type类创建而来。
3). 动态生成类,不能控制类是如何生成的。python3 的metaclass可动态创建类。
4). 很多Web框架都会使用metaclass 来创建类。掌握元类对理解源代码至关重要。eg: ORM框架类

3、自定义元类
metaclass的原理是什么呢? 应用场景: Django(ORM)、元类实现单例模式等。
元类本身而言,实现的功能是: 1. 拦截类的创建 2. 修改类 3. 返回修改之后的类
metaclass自定义元类

# 实现单例模式的方法:
#       1. 装饰器
#       2. new魔术方法
#       3. metaclass自定义元类

class Singleton(type):
    """
    type(name, bases, attrs)
    自定义元类实现单例模式, 父类是type
    """
    # 所有类和实例化对象之间的关系; eg: {'Person': Pseron()}
    cache = {}

    # 1). 为什么是__call__魔术方法?
    def __call__(cls):
        # 判断类是否已经实例化, 如果没有, 实例化后存储到缓存中。 最后将缓存的信息返回给用户。
        if cls not in  cls.cache:
            cls.cache[cls] = super(Singleton, cls).__call__()
        return  cls.cache[cls]


# type('Pseron', (), {})
# 创建以各类Person, 指定创建Person类的类(元类)是type.
# 2. metaclass是在做什么? 指定元类为Singleton。
class Person(object, metaclass=Singleton):  # Person = Singleton.__new__(Person, (objects, ), {})
    pass

# Person是Singleton元类实例化出的对象, Person()就是对象(), 执行Singleton.__call__魔术方法.
p1 = Person()
p2 = Person()
print(p1, p2)

<__main__.Person object at 0x00000146EA0FEE48> <__main__.Person object at 0x00000146EA0FEE48>

二、抽象基类
什么是抽象基类?
抽象基类有两个特点:
1.规定继承类必须具有抽象基类指定的方法
2.抽象基类无法实例化

实现抽象基类可以使用内置的abc模块

import abc
class Human(metaclass=abc.ABCMeta):
    """基类, 定义一个抽象类"""
    @abc.abstractmethod
    def introduce(self):
        print("introduce.....")
    @abc.abstractmethod
    def hello(self):
        print('hello')

class Person(Human):
    # 1).规定继承类必须具有抽象基类指定的方法
    def introduce(self):
        print('person')
    def hello(self):
        print('person hello')

# 2). 抽象基类无法实例化
# h = Human()
p = Person()
p.introduce()
p.hello()
person
person hello

三、自省机制
什么是自省?
1). 在日常生活中,自省(introspection)是一种自我检查行为。
2). 在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及 它能做什么。自省向程序员提供了极大的灵活性和控制力。
3). 例如Python, Ruby, object-C, C++都有自省的能力,这里面的C++的自省的能力最弱, 只能够知道是什么类型,而像Python可以知道是什么类型,还有什么属性。
Python中比较常见的自省(introspection)机制(函数用法)有: dir()、type()、 hasattr(),、setattr()、getattr()、delattr()、isinstance(),通过这些函数,我们能够 在程序运行时得知对象的类型,判断对象是否存在某个属性,访问对象的属性。

四、slots
动态语言与静态语言的不同?

  1. 动态语言:可以在运行的过程中,修改代码
  2. 静态语言:编译时已经确定好代码,运行过程中不能修改

如何去限制实例的属性?

  1. Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性
  2. 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

__slots__限制对象属性

class Date(object):
    # __slots__ 来限制该对象能添加的属性信息
    __slots__ =  '__year', '__month', '__day'
    def __new__(cls, year, month, day):
        self = object.__new__(cls)
        self.__year = year
        self.__month = month
        self.__day = day
        return  self
    @property
    def year(self):
        return  self.__year

    @property
    def month(self):
        return self.__month

    @property
    def day(self):
        return self.__day
    @classmethod
    def today(cls):
        time_t = time.localtime()
        return  cls(time_t.tm_year, time_t.tm_mon, time_t.tm_mday)

    def __str__(self):
        return  '%s-%s-%s' %(self.__year, self.__month, self.__day)



d = Date(2019, 10, 10)
print("对象类型: ", type(d))        # <class 'datetime.date'>
print("判断是否有year这个属性?", hasattr(d, 'year')) # True
print("判断是否有time这个属性?", hasattr(d, 'time')) # False
# setattr(d, 'time', '10:10:10')      # Error
# print('time:', getattr(d, 'time'))  # Error

print(Date.today())
对象类型:  <class '__main__.Date'>
判断是否有year这个属性? True
判断是否有time这个属性? False
2020-1-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值