day28 面向对象:反射,内置函数,类的内置方法
面向对象进阶博客地址链接:
http://www.cnblogs.com/Eva-J/articles/7351812.html
复习昨日内容:
# 包 # 开发规范 # # hashlib # 登录验证 密文密码检测 # 密文存储 # 加盐 # 动态加盐 # 检测文件一致性 md5 #MD5.update() # configparser : 配置文件相关 #网络编程 ftp #[section1] #o1 = yes # logging : 日志 #记录一些信息和结果 #打日志 #日志就和print #学生管理系统 #需要用户选择的时候打印的提示信息 #一个程序和用户发生文字交互的时候,不能使用logging # 中间结果 错误提示 都可以使用logging # 管理员在某时某刻创建了一个班级 —— logging
今日概要:
# 欠你得内置函数 *** # 反射 ***** # 类的内置双下方法 *** # 面向对象的高级代码和一道面试题 # 看书 # 看源码 # 看博客 #简书 #csdn
内置函数:
#property #classmethod #staticmethod #super #object #isinstance #issubclass #vars # from collections import Iterable # print(isinstance([],Iterable)) # class A:pass # class B(A):pass # b = B() # print(isinstance(b,A)) # print(isinstance(a,object)) # class A:pass # class B(A):pass # print(issubclass(B,A)) # print(issubclass(A,B)) # print(issubclass(A,object)) # print(issubclass(B,object)) #isinstance(对象,类) 判断这个对象是不是这个类或者这个类的子类的实例化 #看全局 # a = 1 # b = 2 # print(vars()) # print(dir()) class A: ''' 描述管理员的类 ''' c = 1 d = 2 def func(self,name): ''' 这个函数整体是做什么的 :param name: 管理员的姓名 :return: 管理员的信息 ''' self.name = 'alex' #看类 # print(vars(A)) a = A() a.func() #看对象 print(vars(a)) ''' 这个函数的主要功能 :return: '''
反射:这个很重要,必须要学会!
# hasattr() # getattr() # setattr() # delattr() # a = 1 # name = 'a' # print(vars()) # print(vars()[name]) # eval() class Management: role = '管理员' def __init__(self,name,sex,phone,mail): self.name = name self.sex = sex self.phone = phone self.mail = mail def creat_class(self): print('创建了一个班级') def creat_teacher(self): print('新建了一条讲师信息') def creat_student(self): print('新建了一条学生信息') # Management.role # if hasattr(Management,'role'): # print(getattr(Management,'role')) # import logging # manager = Management('小雨','女',1233211234567,'xiaoyu@qq.com') # if hasattr(manager,'sex1'): # sex = getattr(manager,'sex1') #使用字符串数据类型的变量名获取属性值 # print(sex) # else: # logging.warning('没有您输入的属性') # cs = getattr(manager,'creat_class') #使用字符串数据类型的方法名调用方法 # cs() # Management.Country = 'China' # setattr(Management,'Country','China') # print(Management.Country) # del Management.Country # delattr(Management,'Country') # print(Management.Country) # manager = Management('小雨','女',1233211234567,'xiaoyu@qq.com') # manager.hobby = '点名' # setattr(manager,'hobby','点名') # print(manager.hobby) #可以通过delattr删除一个类中的方法 # delattr(Management,'creat_class') # manager.creat_class() # def create_course(self): # print('创建了一个课程') # setattr(manager,'create_course',create_course) # manager.create_course(manager) # hasattr(对象名,'属性名') 返回True或False #属性值 = getattr(对象名,'属性名') #方法的内存地址 = getattr(对象名,'方法名') #方法的内存地址() # import demo # # demo.a # print(getattr(demo,'a')) # qq = getattr(demo,'qqxing') # ret = qq('wahaha') # print(ret) # aaa = 'bbb' # import sys # print(sys.modules[__name__]) # print(getattr(sys.modules[__name__],'aaa')) # 对象的反射 # 类的反射 # 模块的反射 # 本模块的反射 : 找到本模块sys.modules[__name__]
反射包括在类中对象的反射,类的反射,以及模块的反射,还有程序所处当前位置的本模块的反射。
类的内置方法:
#str 和 repr # class A: # # pass # def __str__(self): # return 'A的对象' # def __repr__(self): # return 'repr: A的对象' # a = A() # print(a) #本质调用的是__str__,如果没实现,就调用__repr__, 再找不到,用object父类的 # print(a.__str__()) #str却不能给repr做备胎 # print(a.__repr__()) #repr是str的备胎 # 打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值 # print(str(a)) # print(repr(a)) # print('%s'%a) # print('%r'%a) # print(a) # l = list() # print(l) # format_dict={ # 'nat':'{o.name}-{o.addr}-{o.type}',#学校名-学校地址-学校类型 # 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 # 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 # } # class School: # def __init__(self,name,addr,type): # self.name=name # self.addr=addr # self.type=type # # def __format__(self, format_spec): #format_spec = 'nat' # fmt='''===================== # 姓名 : {obj.name} # 班级 : {obj.addr} # =====================''' # return fmt.format(obj=self) # s1=School('oldboy1','北京','私立') # print(format(s1,'nat')) # print(format(s1,'tna')) # print(format(s1,'tan')) # print(format(s1,'asfdasdffd')) #打印学生信息 #姓名 班级 性别 年龄 #===================== # 姓名 : name # 班级 : class #===================== # 析构方法 # 周期 :0 # 12 一个亿个对象 del 对象 # class A: # def __del__(self): # ''' # 析构方法 # 这个方法只有在执行del A类的对象的时候才被触发 # 且先执行代码中的内容,再删除对象 # 如果我删除了这个对象,它跟着还有一些其他的附属的内容也没有用了 # 我们就可以在这个方法中回收掉 # ''' # print('执行我啦!') # self.b.close() # f = open('file','w') # a = A() # a.b = f # del a # print(a) class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): if item == 1: print('hahaha') # 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) f1 = Foo('sb') #访问属性的方式变了 #对象名.属性 # f1=Foo('sb') # f1['age']=18 #给f1添加一个属性 # del f1['age'] #删除属性 # # f1.name # print(f1['name']) # # f1.__dict__['age'] = 18 # f1['age1']=19 # del f1.age1 #删除属性 # # f1['name']='alex' # print(f1.__dict__) #pytho内部的约定 #关于item : 对象访问 如果是 对象名[],是因为内部实现了item系列的方法 # 对象的实例化 #创造一个裸地对象 —— __new__ **** #初始化 # 单例模式 —— 设计模式 # 一个类 从头到尾 只创建 一个对象 # class Singleton: # def __new__(cls, *args): # if not hasattr(cls, '_instance'): # cls._instance = object.__new__(cls) # return cls._instance # # def __init__(self,name): # self.name = name # # one = Singleton('alex') # print(one.name) # two = one # two.name = 'egon' # # two = Singleton('egon') # # print(two.name) # # print(one.name) # print(id(one),id(two)) # class Foo: # def __init__(self): # pass # # def __call__(self, *args, **kwargs): # print('__call__') # # Foo()() #对象名() # class A: # def __eq__(self,obj): #equal : 相等 # # if self.a == obj.a and self.b == obj.b: # return True # a = A() # b = A() # a.name = 'alex' # b.name = 'egon' # print(a == b) # from collections import namedtuple # Card = namedtuple('Card',['rank','suit']) # class FranchDeck: # ranks = [str(n) for n in range(2,11)] + list('JQKA') # suits = ['红心','方板','梅花','黑桃'] # def __init__(self): # self._cards = [Card(rank,suit) for rank in FranchDeck.ranks # for suit in FranchDeck.suits] # # def __len__(self): # return len(self._cards) # # def __getitem__(self, item): # return self._cards[item] # # def __setitem__(self, key, value): # self._cards[key] = value # # deck = FranchDeck() # # print(deck._cards) # print(deck[0]) # # from random import choice # # print(choice(deck)) # # print(choice(deck)) # from random import shuffle # shuffle(deck) # print(deck._cards) # 一个类 有 100个 对象,每一个对象都拥有三个属性:name,sex,age # 如果两个对象的name和sex属性完全一致 # 我就认为这是一个对象 # 请对这100个对象进行去重 # class Person: # def __init__(self,name,age,sex): # self.name = name # self.age = age # self.sex = sex # def __hash__(self): # return hash(self.name+self.sex) # def __eq__(self, other): # if self.name == other.name and self.sex == other.sex:return True # # p_lst = [] # for i in range(84): # p_lst.append(Person('egon',i,'male')) # print(set(p_lst))
下面这一版的内置方法是添加了更多的更详尽注释的:
# str 和 repr # class A: # # pass # def __str__(self): # return 'A的对象' # def __repr__(self): # return 'repr: A的对象' # a = A() # print(a) # 本质调用的是__str__,如果没实现,就调用__repr__, 再找不到,用object父类的 # print(a.__str__()) # str却不能给repr做备胎 # print(a.__repr__()) # repr是str的备胎 # 打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值 # print(str(a)) # print(repr(a)) # print('%s'%a) # print('%r'%a) # print(a) # l = list() # print(l) # format_dict={ # 'nat':'{o.name}-{o.addr}-{o.type}',#学校名-学校地址-学校类型 # 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址 # 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名 # } # class School: # def __init__(self,name,addr,type): # self.name=name # self.addr=addr # self.type=type # # def __format__(self, format_spec): #format_spec = 'nat' # fmt='''===================== # 姓名 : {obj.name} # 班级 : {obj.addr} # =====================''' # return fmt.format(obj=self) # s1=School('oldboy1','北京','私立') # print(format(s1,'nat')) # print(format(s1,'tna')) # print(format(s1,'tan')) # print(format(s1,'asfdasdffd')) # 打印学生信息 # 姓名 班级 性别 年龄 # ===================== # 姓名 : name # 班级 : class # ===================== # 析构方法 # 周期 :0 # 12 一个亿的对象 del 对象 # class A: # def __del__(self): # ''' # 析构方法 # 这个方法只有在执行del A类的对象的时候才被触发 # 且先执行代码中的内容,再删除对象 # 如果我删除了这个对象,它跟着还有一些其他的附属的内容也没有用了 # 我们就可以在这个方法中回收掉 # ''' # print('执行我啦!') # self.b.close() ## 这里self就是a,self是实例化的对象,所以a.b就是self.b # 所以这里也解释了为什么这里的b要和下面a后面的b保持一致的原因 # f = open('file','w') # a = A() # a.b = f ## 这里是添加一个属性,a是A实例化出来的一个对象,a.b = f 这是把对象所添加的属性赋值给f # del a # print(a) class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): if item == 1: print('hahaha') # 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) f1 = Foo('sb') # 访问属性的方式变了 # 对象名.属性 # f1=Foo('sb') # f1['age']=18 #给f1添加一个属性 # del f1['age'] #删除属性 # # f1.name # print(f1['name']) # # f1.__dict__['age'] = 18 # f1['age1']=19 # del f1.age1 #删除属性 # # f1['name']='alex' # print(f1.__dict__) #pytho内部的约定 #关于item : 对象访问 如果是 对象名[],是因为内部实现了item系列的方法 # 对象的实例化 # 创造一个裸地对象 —— __new__ **** # 初始化 # 单例模式 —— 设计模式 # 一个类 从头到尾 只创建 一个对象 # class Singleton: # def __new__(cls, *args): # if not hasattr(cls, '_instance'): # cls._instance = object.__new__(cls) # return cls._instance # # def __init__(self,name): # self.name = name # # one = Singleton('alex') # print(one.name) # two = one # two.name = 'egon' # # two = Singleton('egon') # # print(two.name) # # print(one.name) # print(id(one),id(two)) # class Foo: # def __init__(self): # pass # # def __call__(self, *args, **kwargs): # print('__call__') # # Foo()() #对象名() # class A: # def __eq__(self,obj): #equal : 相等 # # if self.a == obj.a and self.b == obj.b: # return True # a = A() # b = A() # a.name = 'alex' # b.name = 'egon' # print(a == b) # from collections import namedtuple # Card = namedtuple('Card',['rank','suit']) # class FranchDeck: # ranks = [str(n) for n in range(2,11)] + list('JQKA') # suits = ['红心','方板','梅花','黑桃'] # def __init__(self): # self._cards = [Card(rank,suit) for rank in FranchDeck.ranks # for suit in FranchDeck.suits] # # def __len__(self): # return len(self._cards) # # def __getitem__(self, item): # return self._cards[item] # # def __setitem__(self, key, value): # self._cards[key] = value # # deck = FranchDeck() # print(deck._cards) # print(deck[0]) # # from random import choice # # print(choice(deck)) # # print(choice(deck)) # from random import shuffle # shuffle(deck) # print(deck._cards) # 一个类 有 100个 对象,每一个对象都拥有三个属性:name,sex,age # 如果两个对象的name和sex属性完全一致 # 我就认为这是一个对象 # 请对这100个对象进行去重 class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): # 这里使用hash方法把字符串拼接起来,得到一个新的字符串, # 如果得到的新的字符串都相同那么这两个元素就是想等的,不仅仅是字符串可以用hash,hash是不可变的数据类型, # (可hash不可变数据类型) return hash(self.name+self.sex) def __eq__(self, other): # 我们去重需要使用集合,因为集合的最大特点就是去重,那么集合里面不仅仅是包含了不可变 # 数据类型,还有可变数据类型,当我们遇到可变数据类型的时候那么我们就需要使用eq去判断他们的值是否相等了, # 这样使得程序更加趋于完善,可以hold住更多的可能 if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon', i, 'male')) print(set(p_lst)) # 一句话总结就是可hash属于不可变的数据类型,需要使用hash去判断是否相等, # 那么不可hash可变的数据类型呢,就不能够使用hash去判断了,需要使用eq去判断是否相等