zoukankan      html  css  js  c++  java
  • Python3笔记043

    第7章 面向对象程序设计

    • 7.1 面向对象概述
    • 7.2 类的定义
    • 7.3 类的实例化
    • 7.4 访问限制
    • 7.5 继承
    • 7.6 封装
    • 7.7 多态
    • 7.8 装饰器
    • 7.9 特殊方法

    7.9 特殊方法

    __format__

    用于将对象格式化输出

    class Person:
        def __init__(self, name, age, city):
            self.name = name
            self.age = age
            self.city = city
    
        def __format__(self, format_spec):
            fmt = {
                '-': '{obj.name}-{obj.age}-{obj.city}',
                '/': '{obj.name}/{obj.age}/{obj.city}'
            }[format_spec]
            return fmt.format(obj = self)
    
    p = Person('Kitty', 19, 'HZ')
    
    # format 函数会调用对象的绑定方法 __format__
    print(format(p, '-'))  
    print(format(p, '/'))
    
    # 输出结果:
    Kitty-19-HZ
    Kitty/19/HZ
    

    __del__

    析构方法,当对象在内存中被释放时,会自动触发执行。但是此方法一般无须定义,因为Python解释器会来完成内存的分配和释放工作,所以,析构方法的调用是由解释器在进行垃圾回收时自动触发执行的。

    class Person:
        def __init__(self, name, age, city):
            self.name = name
            self.age = age
            self.city = city
    
        def __del__(self):
            print('delete...')
    
    p = Person('Kitty', 19, 'HZ')
    del p
    
    # 输出结果:
    delete...
    

    item系列

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __getitem__(self, item):
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, item):
            self.__dict__.pop(item)
    
        def __delattr__(self, key):
            self.__dict__.pop(key)
    
    p = Person('Kitty', 19)
    print(p['name'])    # Kitty,调用 __getitem__ 方法
    
    p['age'] = 18
    print(p['age'])     # 18
    
    p['city'] = 'HZ'       
    print(p.__dict__)   # 调用 __setitem__ 方法
    # {'name': 'Kitty', 'age': 18, 'city': 'HZ'}
    
    del p['city']       # 调用 __delitem__ 方法
    print(p.__dict__) 
    # {'name': 'Kitty', 'age': 18}
    
    del p.age           # 调用 __delattr__ 方法
    print(p.__dict__)
    # {'name': 'Kitty'}
    

    __len__

    len(obj) 会调用obj的 __len__ 方法

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __len__(self):
            return len(self.__dict__)
    
    p = Person('Kitty', 19)
    print(len(p))       # 2
    

    __call__

    对象后面加括号,就会触发 __call__方法的执行,即调用方式:对象() 或者 类()()

    class Person:
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        def __call__(self):
            print('hello' + ' ' + self.__name)
    
    p = Person('Kitty', 19)()     # hello Kitty
    # p()
    

    __new__

    在类的是实例化过程中,第一个被调用的是 __new__方法。在对象的初始化之前首先要创建对象,__new__方法正是用来创建这个对象~

    类的实例化过程也可以通过如下语句来实现:

    >>> p = object.__new__(Person) 
    >>> Person.__init__(p, 'Kitty', 18)
    >>> p.name
    'Kitty'
    

    在Person类中重写 __new__ 方法:

    class Person:
        country = "China"
        def __new__(cls, name, age):
            print('__new__ called')
            return super(Person, cls).__new__(cls)
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def speak(self, word):
            print(word)
    
    p = Person('Kitty', 18)          # 实例化对象
    print('name : %s' % p.name)
    
    # 输出结果:
    __new__ called
    name : Kitty
    

    可以看到 new 方法 是先于 __init__ 方法被调用的~
    类的实例化过程大致步骤如下:
    1、p = Person('Kitty', 18) ,会调用 Person类的 new 方法,并传递 name 和 age 参数
    2、new 方法 会创建一个 Person类的对象并返回
    3、最后利用这个对象调用类的 __init__ 方法 完成初始化, __init__ 方法的第一个参数是self,对象在调用 __init__ 方法时会将自己当做参数传递给 这个self。

    单例模式

    重写 new 来实现单例模式~

    class Person:
       def __new__(cls, *args, **kwargs):
           if not hasattr(cls, '_instance'):
               cls._instance = super(Person, cls).__new__(cls, *args, **kwargs)
           return cls._instance
    
    p1 = Person()
    p2 = Person()
    
    print(p1)    # <__main__.Person object at 0x108eb6438>
    print(p2)    # <__main__.Person object at 0x108eb6438>
    

    对象的内存地址相同,则表示为同一个对象~

    __hash____eq__

    在判断两个对象是否一致时,往往会用到这两个函数~

    __hash__

    class Person:
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        def __hash__(self):
            return hash(str(self.__name))
    
    p = Person('Kitty', '19')
    print(hash(p))
    

    __eq__

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __eq__(self, obj):
            if self.name == obj.name and self.age == obj.age:
                return True
    
    p1 = Person('Kitty', '19')
    p2 = Person('Kitty', '19')
    print(p1 == p2)     # True
    

    集合(set)是一个无序不重复元素的序列。集合中只能存放不可变对象(可hash的)。在向 set 集合中添加对象时,会通过调用对象的 __hash____eq__ 这两个方法来判断集合中是否已经存在一样的对象~

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __hash__(self):
            print('调用了__hash__方法')
            return hash(self.name)
        def __eq__(self, obj):
            print('调用了__eq__方法')
            return self.name == obj.name and self.age == obj.age
    
        def __str__(self):
            return '(' + self.name + ', ' + self.age + ')'
    
    p1 = Person('Tom', '19')     # 调用了__hash__方法
    p2 = Person('Jeff', '20')      # 调用了__hash__方法
    my_set = {p1, p2}
    
    for i in my_set:
        print(i)              # (Jeff, 20), (Tom, 19)
    

    在向 set 集合中添加对象时,会首先调用对象的 hash 若是 返回的 hash值不一样,则认为不是重复的对象,进行添加~

    p1 = Person('Tom', '19')      # 调用了__hash__方法
    p2 = Person('Tom', '20')      # 调用了__hash__方法,调用了__eq__方法
    my_set = {p1, p2}
    
    for i in my_set:       # (Tom, 20), (Tom, 19)
        print(i)
    

    若是返回的hash值有重复的,则会接着调用对象 __eq__ 方法,若 __eq__ 方法的返回值为False,则认为不是重复对象,进行添加,若返回为True,则不进行添加~

  • 相关阅读:
    html 标签分类
    第三课 物理地址和几条汇编指令
    第二课 寄存器
    第一课 基础知识
    利用队列进行二叉树的层次遍历
    二叉树前序创建三种遍历 代码亲测
    记录
    My97 DatePicker 全局显示、隐藏
    Available Memory Is Low
    connect by prior...start with...
  • 原文地址:https://www.cnblogs.com/infuture/p/13352851.html
Copyright © 2011-2022 走看看