深入Python的类和对象
- 多态:不同的子类对象,可以调用相同的父类方法,通过改写父类的方法,产生不同的执行结果
- instance和type的区别: instance能够顺延到父类,比对对象与父类是否类型一致。而type只能比对当前对象
- 类变量和实例变量:
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("-")) return Date(int(year), int(month), int(day)) @staticmethod def valid_str(date_str): year, month, day = tuple(date_str.split("-")) if int(year)>0 and (int(month) >0 and int(month)<=12) and (int(day) >0 and int(day)<=31): return True else: return False @classmethod def from_string(cls, date_str): year, month, day = tuple(date_str.split("-")) return cls(int(year), int(month), int(day)) def __str__(self): return "{year}/{month}/{day}".format(year=self.year, month=self.month, day=self.day) if __name__ == "__main__": new_day = Date(2018, 12, 31) new_day.tomorrow() print(new_day) #2018-12-31 date_str = "2018-12-31" year, month, day = tuple(date_str.split("-")) new_day = Date(int(year), int(month), int(day)) print (new_day) #用staticmethod完成初始化 new_day = Date.parse_from_string(date_str) print (new_day) #用classmethod完成初始化 new_day = Date.from_string(date_str) print(new_day) print(Date.valid_str("2018-12-32"))类方法比静态方法好的地方就是:静态方法return时,调用的时候必须与原类名相同。而类方法如果有返回值,就不用与原类名字相同。一般用cls代替。(当然其他的名字也可以)
- 数据封装和私有属性:self.__birthday = birthday 如果不对数据进行封装,那么在类的外面直接对类属性改值,用户能够看到该属性。一般使用get和set对该属性进行封装,然后通过该方法对该属性进行读取和修改。一般在私有属性,Python会对该属性名进行变形,改成_classname__attr 例如 user = User, print (user._User__birthday) .......如果子类继承父类,需要修改父类的私有属性通过修改__init__方法
- Python的自省机制:通过一定的机制查询到对象的内部结构。通过User.__dict__方法查询属性 (会使用__mro__)方法,类和实例都可以用。还有dir()方法
- mixin 案例,因为不怎么推荐使用多继承:
#mixin模式特点
# 1. Mixin类功能单一,简单。一般只有一个方法实现一个功能。名字尽量以Mixin结尾
# 2. 不和基类关联,可以和任意基类组合(就可以多个mixin 来重组成一个功能较复杂的类), 基类可以不和mixin关联就能初始化成功
# 3. 在mixin中不要使用super这种用法 -
#try except 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
这里值得注意的是为什么最后返回值是4而不是123。因为1234按照顺序押入栈中后,取最上面的值,所以返回的是4
- 上下文管理器协议:
#上下文管理器协议 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()
使用with 语句,就会自动调用enter和exit两个魔法函数
-
import contextlib @contextlib.contextmanager def file_open(file_name): print ("file open") yield {} print ("file end") with file_open("bobby.txt") as f_opened: print ("file processing")
简化了上下文管理器,在yield生成器上面的是enter方法,然后下面是exit方法。这样就使整个按照顺序的方法来完成。