一、上节回顾:
#包
#hashlib
#登录验证,密文密码检测
#密文cunc
#加盐
#动态加盐
#检测文件一致性 MD5
#MD5.update()
#configparse:配置文件相关
#网络变成 ftp
#[section]
#ol=yes
#logging:日志
#记录一些信息和结果
#打日志
#日志和print
#学生管理系统
#需要用户选择的时候打印提示信息
#一个程序和用户发生文字交互的时候,不能使用logging
#中间结果,错误提示么都可以使用logging
#管理员在某时刻创建了一个班级————logging
二、今日内容:
(1)内置函数 ***
(2)反射*****
(3)类的内置双下方法 ***
(4)面向对对象的高级代码和一道面试题
#看书
#看源码
#看博客
#简书
#csdn
(一)内置函数
#property
#classmethod
#saticmethod
#super
#object
#isinstance
1、isinstance
(对象,类)判断这个对象是不是这个类或者这个类的子类的实例化
from collections import Iterable print(isinstance([],Iterable)) #True class A:pass class B(A):pass b=B() print(isinstance(b,A)) #True print(isinstance(b,object))#True
2、issubclass
(子类,类)判断一个类是否是另一个类的子类
class A:pass class B(A):pass print(issubclass(B,A)) #True print(issubclass(A,B)) #False print(issubclass(A,object)) #True print(issubclass(B,object)) #True
3、补充:注释的添加
函数的注释添加
4、vars
# 看全局 # a=1 # b=2 # print(vars()) # print(dir()) class A: c=1 d=2 def func(self): self.name="alex" # 看类 # print(vars(A)) a=A() a.func() # 看对象 print(vars(a)) #{'name': 'alex'}
(二)反射(非常重要)
对象的反射
类的反射
模块的反射
#hasattr()
#getattr()
#setattr()
#delattr()
python面向对象中的反射:通过字符串的形式操作相关的属性。python中一切事物的对象都可以使用反射
1、getattr(与eval的区别在于getattr不会存在的信息会报错,比较安全
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("创造了一个学生信息") manager=Management("小鱼","女",12331234567,"xiaoyu@qq.com") func=input("func: ") f=getattr(manager,func) f()
解析:
(1)方法名的调用
cs=getattr(manager,"creat_class") 使用字符串数据类型的方法名调用方法 cs() #创造了一个班级信息
(2)属性的取用
#属性的的调用 f=getattr(manager,"phone") #使用字符串数据类型的变量名获取属性值 print(f) #12331234567
2、hasattr
(1)hasattr和getattr 组合调用
import logging manager=Management("小鱼","女",12331234567,"xiaoyu@qq.com") if hasattr(manager,"sex1"): sex=getattr(manager,"sex1") #使用字符串数据类型的变量名获取属性值 print(sex) else: logging.warning("没有您输入的属性") #WARNING:root:没有您输入的属性
(2)类名的使用
if hasattr(Management,"role"): print(getattr(Management,"role")) #管理员
3、setattr delattr(了解)字符串类型
# Management.Country="China" setattr(Management,"Country","China") #增加 print(Management.Country) #China # del Management.Country delattr(Management,"Country") #s删除 # print(Management.Country)
(1)对象添加属性:
(2)使用delattr 删除一个类中的方法
delattr(Management,"creat_class") manager.creat_class()
(3)绑定的方法(不常用)
def create_course(self): print("创建了一个课程") setattr(manager,"create_course",create_course) manager.create_course(manager)
总结:python的一切皆对象
hasattr(类名(或者对象名),“属性名”) 返回True 或False
属性值=getattr(类名(或者对象名),“属性名”)
方法的内存地址=getattr(类名(或者对象名),“方法名”)
方法的内存地址()
(三)模块的反射
1、创建一个模块
2、调用模块中的属性
import demo print(getattr(demo,"a"))
#1
3、调用模块中的函数
import demo qq=getattr(demo,"qqxing") #调用函数名 qq("wahaha") #给定一个参数 #qqxing: wahaha
4、接收模块中函数的返回值
import demo qq=getattr(demo,"qqxing") #调用函数名 ret=qq("wahaha") #给定一个参数 print(ret) #接收函数的返回值 #qqxing: wahaha # 大螃蟹
5、反射本模块的代码(核心是找到本模块sys.modules[__name__])
aaa="bbb" import sys print(sys.modules[__name__]) print(getattr(sys.modules[__name__],"aaa")) #bbb
解析:看有道截图
总结:
(四)类的内置方法
__str__和__repr__ 改变对象的字符串显示
1、__str__方法
class A: pass def __str__(self): return "A的对象" a=A() print(a) print(a.__str__()) #打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值 print("%s"%a)
解析:
2、__repr__方法
(1)注释__repr__方法
class A: pass def __str__(self): return "A的对象" #def __repr__(self): #return "repr:A 的对象" a=A() print(a) print(a.__str__()) print("%s"%a) # A的对象 # A的对象 # A的对象
(2)注释__str__方法
class A: pass def __str__(self): return "A的对象" # def __repr__(self): # return "repr:A 的对象" a=A() print(a) print(a.__str__()) print(a.__repr__()) print("%s"%a) #s=str print("%r"%a) #r=repr print(str(a)) print(repr(a)) # A的对象 # A的对象 # <__main__.A object at 0x000000000220D630> # A的对象 # <__main__.A object at 0x000000000220D630> # A的对象 # <__main__.A object at 0x000000000220D630>
解析:
3、format(不重要)
格式化输出:
format_dict={ "nat":"{obj.name}-{obj.addr}-{obj.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): if not format_spec or format_spec not in format_dict: format_spec="nat" fmt=format_dict[format_spec] return fmt.format(obj=self) s1=School("oldboy1","北京","私立") print(format(s1,"nat")) print(format(s1,"tna")) print(format(s1,"tan")) print(format(s1,"erasikfdhkasdffd")) # oldboy1-北京-私立 # 私立:oldboy1:北京 # 私立/北京/oldboy1 # oldboy1-北京-私立
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.type}*{obj.addr}*{obj.name}" return fmt.format(obj=self) s1=School("oldboy1","北京","私立") print(format(s1,"nat")) # 私立*北京*oldboy1
解析:
大作业中的格式化输出:
4、析构方法:
(1)主动删除(运行步骤从上往下)
class A: def __del__(self): print("执行我啦") a=A() del a import time time.sleep(2) a=A()
(2)析构函数的应用场景,文件先关闭后删除
class A: def __del__(self): self.f.close() print("执行我啦") f=open("file","w") a=A() a.f=f del f import time time.sleep(2)
总结:
5、item系列
__getitem__\__setitem__\__delitem__
(1:访问的方式变了
#对象名.属性
class Foo: def __init__(self,name): self.name=name 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) f1=Foo("sb") f1["age"]=18 #给f1添加一个属性 f1["age1"]=19 del f1.age1 #删除属性 del f1["age"] #删除属性 f1["name"]="alex" print(f1.__dict__) # del obj.key时,我执行 # del obj[key]时,我执行 # {'name': 'alex'}
关于 item :对象访问,如果是对象名[],是因为内部实现了item系列的方法
6、__new__方法
面试的时候会用到
class Singleton: def __new__(cls, *args, **kwargs): 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="agon"
7、__call__
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print("__call__") obj=Foo() #执行__init__ obj() #执行__call__ obj=Foo()() #对象后面加()就调用__call__
8、__len__方法
class A: def __init__(self): self.a=1 self.b=2 def __len__(self): return len(self.__dict__) a=A() print(len(a)) #2
9、__hash__
class A: def __init__(self): self.a=1 self.b=2 def __hash__(self): return hash(str(self.a)+str(self.b)) a=A() print(hash(a))
10、__eq__
class A: def __init__(self): self.a=1 self.b=2 def __eq__(self,obj): if self.a==obj.a and self.b==obj.b: return True a=A() b=A() print(a==b)#True
纸牌游戏
from collections import namedtuple Card=namedtuple("Card",["rank","suit"]) c1=Card(2,"梅花") 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 deck=FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(c1.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[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5])
面试题:
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(p_lst) print(set(p_lst))