zoukankan      html  css  js  c++  java
  • 二十六. Python基础(26)--类的内置特殊属性和方法

    二十六. Python基础(26)--类的内置特殊属性和方法

    ● 知识框架

    ● 类的内置方法/魔法方法案例1: 单例设计模式

    # 类的魔法方法

    # 案例1: 单例设计模式

    class Teacher:             #创建一个老师类

        __isinstance = None     #创建一个私有静态变量, 准备用来指向一个裸着的对象

        def __new__(cls, *args, **kwargs): #创建一个裸着的对象

            if not cls.__isinstance:         #如果__isinstance属性为None

                cls.__isinstance = object.__new__(cls) #object.__new__创建一个裸着的对象

            return cls.__isinstance         #返回一个对象

     

        def __init__(self,name,cloth):     #self就是cls.__isinstance返回的对象

            self.name = name                 #selfname属性赋值

            self.cloth = cloth             #selfcloth属性赋值

     

    p1 = Teacher('Arroz','white')

    print(p1.name)

    p2 = Teacher('Paul','black')

    p3 = Teacher('Paul','black')

    print(p1.name)

    print(p2)

    print(p3)

     

     

    ● 类的内置方法/魔法方法案例2: 综合案例

    # 案例2: 综合案例

    class Person:

        # __init__是在类实例创建之后调用, __new__方法正是创建这个类实例的静态方法

        def __new__(cls, *args, **kwargs): # __new__()方法的第一个参数必须是当前类cls(也可以用其它名字,但习惯写成cls),后续参数则可以自由指定

            print('__new__')

            return object.__new__(cls) # object可以用其它新式类代替, 但不要写本类(如这里的Person)

    # 我们可以自由选择任意一个的其他的新式类(必定要是新式类,只有新式类必定都有new(),因为所有新式类都是object的后代,而经典类则没有new() 方法)的new()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死循环。

    # __new__()用来创建实例, 在返回的实例上执行__init__()方法. 当__new__()的参数是当前类时(可以写成__new__(cls), 或者__new__(Person)), __init__()方法才会自动执行, 否则, 如果参数是其它类, __init__()不执

    #还可以写成: return super().__new__(cls)或return super(Person, cls).__new__(cls)

    # __new()__是生产部经理,它以决定是否将原料提供给该生产部工人,即init()

     

        def __init__(self,name,age,sex): # 构造方法, __init__()方法的第一个参数必须是当前类的对象self(也可以用其它名字,但习惯写成self),后续参数则可以自由指定

            self.name=name

            self.age=age

            self.sex=sex

     

        def __hash__(self):

            return hash(self.name+self.sex) # self.nameself.sex两个字符串结合, 作为hash()的实参

     

        def __eq__(self, other):

            if self.name==other.name and self.sex==other.sex:return True

     

        def __str__(self): # 定义当被str()调用时的行为, 定以后, print(对象)相当于 对象.__str__()

            return self.name+", "+self.sex

     

        def __repr__(self):

            return repr(self.name+", "+self.sex)

     

        def __call__(self,x,y):

            return x*y

     

        def __len__(self):

            return len(self.__dict__)

     

        def __getitem__(self, item):

            print(self.__dict__[item])

     

        def __setitem__(self, key, value):

            self.__dict__[key]=value

     

        def __delitem__(self, key):

            print('del obj[key],我执行')

            self.__dict__.pop(key)

     

        def __delattr__(self, item):

            print('del obj.key,我执行')

            self.__dict__.pop(item)

     

        def __del__(self):

            print('__del__')

     

    p1=Person('Arroz',20,'Male')

    p2=Person('Arroz',30,'Male')

    p3=Person('Arroz',40,'Male')

    p4=Person('Arroz',50,'Female')

    p_lst=[p1,p2,p3,p4] # 三个对象的地址不同, 但值相同

    print(set(p_lst))

    print('-------------------')

    print(p1)

    print(str(p1))

    print(repr(p1))

    print('-------------------')

    print(p1(3,7))

    print('-------------------')

    print(len(p1))

    print('-------------------')

    print('before:', p4.__dict__)

    p4['age']=60 #与魔法方法__setitem__()相关

    p4['hobby']='swimming'

    print('after1:', p4.__dict__)

    del p4.hobby

    del p4['age']

    p4['name']='Alex'

    print('after2:', p4.__dict__)

    print('-------------------')

     

    # 反射:通过字符串操作对象的相关属性

    print(hasattr(p4,'name'))

    print(getattr(p4,'name'))

    setattr(p4,'Nationality','China')

    delattr(p4,'name')

    print(p4.__dict__)

     

    '''

    如果没有定义__str__()__repr__(), 那么打印结果是各对象的地址, 例如:

    {<__main__.Person object at 0x000000000265B9E8>, <__main__.Person object at 0x000000000265B940>}

    '''

    __new__

    __new__

    __new__

    __new__

    {'Arroz, Female', 'Arroz, Male'}

    -------------------

    Arroz, Male

    Arroz, Male

    'Arroz, Male'

    -------------------

    21

    -------------------

    3

    -------------------

    before: {'name': 'Arroz', 'age': 50, 'sex': 'Female'}

    after1: {'name': 'Arroz', 'age': 60, 'sex': 'Female', 'hobby': 'swimming'}

    del obj.key时,我执行

    del obj[key]时,我执行

    after2: {'name': 'Alex', 'sex': 'Female'}

    -------------------

    True

    Alex

    del obj.key时,我执行

    {'sex': 'Female', 'Nationality': 'China'}

    __del__

    __del__

    __del__

    __del__

    ● 类的内置方法/魔法方法案例3: 斐波那契数列数列

    # 案例3: 斐波那契数列

    # 一个实现了__iter__()__next__()方法的类可以作为迭代器使用。

    # __next__方法:返回迭代器的下一个元素(py2中是next())

    # __iter__方法:返回迭代器对象本身

     

    class Fib(object):

        def __init__(self):

            self.a, self.b = 0, 1 # 初始化两个计数器ab

     

        def __iter__(self):

            return self # 实例本身就是迭代对象,故返回自己

     

        def __next__(self): # py2中是next()

            self.a, self.b = self.b, self.a + self.b # 计算下一个值

            if self.a > 10: # 退出循环的条件

                raise StopIteration();

            return self.a # 返回下一个值

     

    # Fib()是一个生成器

    print([i for i in Fib()]) # [1, 1, 2, 3, 5, 8]

    print(list(Fib())) # [1, 1, 2, 3, 5, 8]

    ● 元类

    ● 元类案例

    print('1. Metaclass declaration')

     

    class Meta(type):

        def __init__(cls, name, bases, attrd):

            super(Meta, cls).__init__(name, bases, attrd)

            print('3. Create class %r' % (name))

     

    print('2. Class Foo declaration')

     

    class Foo(metaclass = Meta):

        def __init__(self):

            print('*. Init class %r' % (self.__class__.__name__))

     

     

    class Child(Foo):

        pass

     

    print('4. Class Foo f1 instantiation')

    f1 = Foo()

     

    print('5. Class Foo f2 instantiation')

    f2 = Foo()

    '''

    1. Metaclass declaration

    2. Class Foo declaration

    3. Create class 'Foo'

    3. Create class 'Child'

    4. Class Foo f1 instantiation

    *. Init class 'Foo'

    5. Class Foo f2 instantiation

    *. Init class 'Foo'

    '''

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

    print(Meta.__class__) # <class 'type'>

    print(type(Foo)) # <class '__main__.Meta'>

    print(Foo.__class__) # <class '__main__.Meta'>

    print(type(Child)) # <class '__main__.Meta'>

    print(Child.__class__) # <class '__main__.Meta'>

    class Te(object):

        def __new__(cls,a,b):

            print('__new__', a,b)

            return object.__new__(cls)

     

        def __init__(self,a,b):

            print("this is a test")

            print('__init__', a, b)

     

    a = Te(12,23)

     

    '''

    __new__ 12 23

    this is a test

    __init__ 12 23

    '''

    # 不能写class Te(type), 因为type是一个meta class,不是class,所以class不能继承于type

    ● 元类的声明

    # 声明元类的方法:

    class Foo(object): #py2

        __metaclass__ = something

     

    class Foo(metaclass=something): #py3

    ● 类的方法的装饰器

    # 装饰器在类中

    class A(object):

        def outer(func):

            def inner(self):

                print("222")

                r = func(self)

                print("333")

                return r

     

            return inner

     

        @outer

        def f(self):

            print("000")

     

     

    obj = A()

    obj.f()

     

    print("================")

     

    # 装饰器不在类中

    def outer(func):

        def inner(self):

            print("222")

            r = func(self)

            print("333")

            return r

     

        return inner

     

    class S(object):

        @outer

        def f(self):

            print("000")

     

    a = S()

    a.f()

    222

    000

    333

    ================

    222

    000

    333

  • 相关阅读:
    年年岁岁花相似,岁岁年年竟相同
    两情相悦,亦或情投意合
    FreeBSD学习笔记1
    MySQL学习笔记2
    门户网站镜像站以及CDN技术
    候车
    MySQL学习笔记1
    JDBC | 第一章: 快速开始使用JDBC连接Mysql数据库之简单CRUD
    JDBC | 第零章: 什么是JDBC?
    JDBC | 第二章: JDBC之批量更新,添加,和删除操作
  • 原文地址:https://www.cnblogs.com/ArrozZhu/p/8396736.html
Copyright © 2011-2022 走看看