深入类和对象

mac2022-06-30  26

                                              深入类和对象

一、鸭子类型和多态

    1、定义:当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

    2、示例:

        (1) 示例一:            

class Cat(object): def say(self): print("I am a cat") class Dog(object): def say(self): print("I am a dog") class Duck(object): def say(self): print("I am a duck") animal_list = [Cat, Dog, Duck] for animal in animal_list: animal().say() 运行结果: I am a cat I am a dog I am a duck

        (2) 示例二:            

class Cat(object): def say(self): print("I am a cat") class Dog(object): def say(self): print("I am a dog") def __getitem__(self, item): return "dog" class Duck(object): def say(self): print("I am a duck") class Company(object): def __init__(self, employee_list): self.employee = employee_list def __getitem__(self, item): return self.employee[item] def __len__(self): return len(self.employee) company = Company(["tom", "bob", "jane"]) a = ["麻花", "米线"] b = ["小麻花", "大碗米线"] name_tuple = ("大麻花", "小碗米线") name_set = set() name_set.add("大份麻花") name_set.add("小碗粗米线") a.extend(b) print(a) a.extend(name_tuple) print(a) a.extend(name_set) print(a) a.extend(company) print(a) dog = Dog() a.extend(dog) print(a) 运行结果: ['麻花', '米线', '小麻花', '大碗米线'] ['麻花', '米线', '小麻花', '大碗米线', '大麻花', '小碗米线'] ['麻花', '米线', '小麻花', '大碗米线', '大麻花', '小碗米线', '小碗粗米线', '大份麻花'] ['麻花', '米线', '小麻花', '大碗米线', '大麻花', '小碗米线', '小碗粗米线', '大份麻花', 'tom', 'bob', 'jane']

二、抽象基类(abc模块)

# 我们去检查某个类是否有某种方法 class Company(object): def __init__(self, employee_list): self.employee = employee_list def __len__(self): return len(self.employee) company = Company(["麻花", "米线"]) print(hasattr(company, "__len__")) # 运行结果: True # 我们在某些情况下希望判定某个对象的类型 from collections.abc import Sized isType = isinstance(company, Sized) print(isType) # 运行结果: True # 我们需要实现强制某个子类必须实现某些方法 # 实现一个web框架,集成cache(redis, cache, memorychache) # 需要设计一个抽象基类,指定子类必须实现某些方法 # 如何去模拟一个抽象基类 import abc class CacheBase(metaclass=abc.ABCMeta): @abc.abstractmethod def get(self, key): pass @ abc.abstractmethod def set(self, key): pass class RedisCache(CacheBase): def set(self, key, value): pass redis_cache = RedisCache() # 运行结果: Traceback (most recent call last): File "/home/caoxuejin/Project/sample/chapter13/c4.py", line 47, in <module> redis_cache = RedisCache() TypeError: Can't instantiate abstract class RedisCache with abstract methods get

三、isinstace和type的区别

class A: pass class B(A): pass b = B() print(isinstance(b, B)) print(isinstance(b, A)) 运行结果: True True print(type(b)) print(type(b) is B) print(type(b) is A) 运行结果: True False

四、类变量和实例变量

class A(object): aa = 1 def __init__(self, x, y): self.x = x self.y = y a = A(2, 3) print(a.x, a.y, a.aa) 运行结果: 2 3 1 A.aa = 11 a.aa = 100 print(a.x, a.y, a.aa) print(A.aa) 运行结果: 2 3 100 11 b = A(4, 5) print(b.x, b.y, b.aa) 运行结果: 4 5 11

五、类和实例属性的查找顺序——mro查找

    1、示例一:        

class A: name = "麻花" a = A() print(a.name) 运行结果: 麻花 class A: name = "麻花" def __init__(self): self.name = "米线" a = A() print(a.name) 运行结果: 米线

    2、mro查找:

# A>>B>>C>>D # 新式类 class D: pass class C(D): pass class B(D): pass class A(B, C): pass print(A.__mro__) 运行结果: (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>) # A>>B>>D>>C>>E class E: pass class D: pass class C(E): pass class B(D): pass class A(B, C): pass print(A.__mro__) 运行结果: (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)

六、类方法、静态方法和实例方法

from datetime import datetime class Date: # 构造函数 def __init__(self, year, month, day): self.year = year self.month = month self.day = day def tomorrow(self): self.day += 1 @staticmethod def parse_from_string(date_str): year, month, day = tuple(date_str.split("-")) new_day = Date(int(year), int(month), int(day)) return new_day @staticmethod def valid_str(date_str): try: datetime.strptime(date_str, "%Y-%m-%d") return True except ValueError: return False @classmethod def from_string(cls, date_str): year, month, day = tuple(date_str.split("-")) new_day = cls(int(year), int(month), int(day)) return new_day def __str__(self): return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day) if __name__ == "__main__": new_day = Date(2019, 10, 6) print(new_day) # 运行结果: 2019/10/6 new_day.tomorrow() print(new_day) # 运行结果: 2019/10/7 date_str = "2019-10-06" year, month, day = tuple(date_str.split("-")) new_day = Date(int(year), int(month), int(day)) print(new_day) # 运行结果: 2019/10/6 # 使用staticmethod完成初始化 new_day = Date.parse_from_string(date_str) print(new_day) # 运行结果: 2019/10/6 # 使用classmethod完成初始化 new_day = Date.from_string(date_str) print(new_day) # 运行结果: 2019/10/6 new_day = Date.valid_str(date_str) print(new_day) # 运行结果: True

七、数据封装和私有属性

    

class Date: # 构造函数 def __init__(self, year, month, day): self.year = year self.month = month self.day = day def __str__(self): return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day) class User: def __init__(self, birthday): # 使用双下划线开头定义私有属性 self.__birthday = birthday def get_age(self): # 返回年龄 return 2019 - self.__birthday.year if __name__ == "__main__": user = User(Date(1993, 12, 12)) print(dir(user)) # 运行结果: ['_User__birthday', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_age'] print(user._User__birthday) # 运行结果: 1993/12/12 print(user.get_age()) # 运行结果: 26

八、python对象的自省机制

class Person: """ 人员信息 """ name = "麻花" class Student(Person): def __init__(self, school_name): self.school_name = school_name if __name__ == "__main__": user = Student("光明小学") # 通过__dict__查询属性 print(user.__dict__) # 运行结果: {'school_name': '光明小学'} user.__dict__["school_addr"] = "北京市" print(user.school_addr) # 运行结果: 北京市 print(Person.__dict__) # 运行结果: {'__module__': '__main__', '__doc__': '\n 人员信息\n ', 'name': '麻花', '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>} print(user.name) # 运行结果: 麻花 # dir() 查看对象的所有属性 print(dir(user)) # 运行结果: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'school_addr', 'school_name'] a = [1, 2, 3] print(dir(a)) # 运行结果: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

九、super真的是调用父类吗?

from threading import Thread class MyThread(Thread): def __init__(self, name, user): self.user = user super.__init__(name=name) # 既然我们重写B的构造函数,为什么还要去调用super? # super到底执行顺序是什么样的? class A: def __init__(self): print("A") class B(A): def __init__(self): print("B") super().__init__() class C(A): def __init__(self): print("C") super().__init__() class D(B, C): def __init__(self): print("D") super(D, self).__init__() if __name__ == "__main__": d = D() # 运行结果: D B C A print(D.__mro__) # 运行结果: (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

十、mixin继承案例——django rest framework

    1、mixin类功能单一;

    2、不和基类关联,可以和任意基类组合,基类可以不和mixin关联就能初始化成功;

    3、在mixin中不要使用super这种用法。

十一、python中的with语句

    1、try---finally:        

# 示例一: def exe_try(): try: print("code started") raise KeyError return 1 except KeyError as e: print("key error") return 2 else: print("other error") return 3 finally: print("finally") return 4 if __name__ == "__main__": result = exe_try() print(result) # 运行结果: code started key error finally 4 # 示例二: def exe_try(): try: print("code started") raise KeyError return 1 except KeyError as e: print("key error") return 2 else: print("other error") return 3 finally: print("finally") # return 4 if __name__ == "__main__": result = exe_try() print(result) # 运行结果: code started key error finally 2

    2、with语句: 

# 上下文管理器协议,重写魔法函数__enter__和__exit__ class Sample: def __enter__(self): print("enter") # 获取资源 return self def __exit__(self, exc_type, exc_val, exc_tb): # 释放资源 print("exit") def do_something(self): print("doing something") with Sample() as sample: sample.do_something() # 运行结果: enter doing something exit

十二、contextlib简化上下文管理器

import contextlib @contextlib.contextmanager def file_open(file_name): print("file open") yield {} print("file end") with file_open("麻花.txt") as fp: print("file processing") # 运行结果: file open file processing file end

 

最新回复(0)