1.isinstace和issubclass
2.staticmethod和classmethod
3.反射(hasattr、getattr、setattr.delattr等四个方法)
4.内置方法
5.logging
6异常处理
7hashlib摘要算法
1.isinstace和issubclass
isinstace判断一个对象是否是一个类的对象。与type的区别;判断对象类型时一定要用type。
class Foo: pass class Son(Foo): pass s = Son() #判断一个对象是不是这个类的对象,传两个参数(对象,类) print(isinstance(s,Son)) print(isinstance(s,Foo)) # print(type(s) is Son) # print(type(s) is Foo)
issubclass判断一个类是不是另一个类的子类。
class Foo: pass class Son(Foo): pass s = Son() #判断一个类是不是另一类的子类,传两个参数(子类,父类) # print(issubclass(Son,Foo)) # print(issubclass(Son,object)) # print(issubclass(Foo,object)) # print(issubclass(int,object))
2.@staticmethod 和@classmthod
@staticmetho(静态方法) 没有默认参数让类里的方法直接被调用,就像正常函数一样。(可以被类和对象调用,不推荐用对象调)
class Student: f = open('student', encoding='utf-8') def __init__(self): pass def func(self): pass @staticmethod #静态方法 : 让类里的方法直接被类调用,就像正常的函数一样 def show_student_info_static(): f = open('student', encoding='utf-8') for line in f: name, sex = line.strip().split(',') print(name, sex) s=Student() s.show_student_info_static() print(Student.show_student_info_static)
@classmethod(类方法) 默认参数是cls,可以直接使用类和对象调用,不推荐用对象调。
class Student: f = open('student', encoding='utf-8') def __init__(self): pass def func(self): pass @classmethod #类方法:默认参数cls,可以直接用类名调用,可以与类属性交互 def show_student_info_class(cls): for line in cls.f: name, sex = line.strip().split(',') print(name, sex) s=Student() s.show_student_info_class() print(Student.show_student_info_class)
总结:
#classmethod和staticmethod #相同:都可以直接被类调用,不需要实例化 #不同: #类方法必须有一个cls参数表示这个类,可以使用类属性 #静态方法不需要,静态方法不能直接使用 #绑定方法 #非绑定方法 #普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象 #类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类 #静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定
#classmethod和staticmethod #相同:都可以直接被类调用,不需要实例化 #不同: #类方法必须有一个cls参数表示这个类,可以使用类属性 #静态方法不需要,静态方法不能直接使用 #绑定方法 #非绑定方法 #普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象 #类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类 #静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定
3.反射(常用:hasattr、getattr;不常用:setattr、delattr)(通过字符串的形式来访问对象的属性与调用对象的方法)(应用范围为 对象、类、模块)
hasattr与getattr:
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def func(self): print(123) egg = Foo() print(hasattr(egg,'name'))#返回bool print(getattr(egg,'name')) if hasattr(egg,'func'): #返回bool Foo_func = getattr(egg,'func') #如果存在这个方法或者属性,就返回属性值或者方法的内存地址 #如果不存在,报错,因此要配合hasattr使用 Foo_func()#执行func方法
不常用的setattr与delattr
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def func(self): print(123) egg = Foo() def show_name(self): print(self.name + ' sb') setattr(egg,'sh_name',show_name)#新增一个方法 # egg.sh_name(egg)#新增方法调用时要传参数就是对象自己 # show_name(egg)#通过函数调用
class Foo: def __init__(self): self.name = 'egon' self.age = 73 def func(self): print(123) egg = Foo() # delattr delattr(egg,'name') print(egg.name)
反射的延伸:(类也是对象)
我们一般用hasattr判断是否有这个属性或方法,用getattr方法调用这个属性或者方法 class Foo: f = 123 #类变量 @classmethod#类方法 def class_method_demo(cls): print('class_method_demo') @staticmethod#静态方法 def static_method_demo(): print('static_method_demo') if hasattr(Foo,'f'):#类属性 print(getattr(Foo,'f')) print(hasattr(Foo,'class_method_demo')) method = getattr(Foo,'class_method_demo') method() print(hasattr(Foo,'static_method_demo')) method2 = getattr(Foo,'static_method_demo') method2() #类也是对象
模块使用反射分为引入模块与本类模块
引入模块:
import my_module print(hasattr(my_module,'test')) # func_test = getattr(my_module,'test') # func_test() getattr(my_module,'test')()
在本模块中的使用
def demo1(): print('喜欢你') import sys # print(__name__) #'__main__' # print(sys.modules) #'__main__': <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'> module_obj =sys.modules[__name__] #sys.modules['__main__'] # module_obj : <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'> # print(module_obj) print(hasattr(module_obj,'demo1')) getattr(module_obj,'demo1')() #在本模块中应用反射
4内置方法
(str与repr)
class Foo: def __init__(self,name): self.name = name # def __str__(self): # return '%s obj info in str'%self.name def __repr__(self): return ' obj info in repr'# f = Foo('egon') # print(f) # print('%s'%f) # print('%r'%f) # print(repr(f)) # f.__repr__() # print(str(f)) #当打印一个对象的时候,如果实现了str,打印返回值 #当str没有被实现的时候,就会调用repr方法 #但是当你用字符串格式化的时候 %s和%r会分别去调用__str__和__repr__ #不管是在字符串格式化的时候还是在打印对象的时候,repr方法都可以作为str方法的替补 #但反之不行 #用于友好的表示对象。如果str和repr方法你只能实现一个:先实现repr
del方法
class Foo: def __del__(self): print('执行我啦') f = Foo() print(123) print(123) print('..........') print(123) print(123) print(123)
__new__方法
class A: def __init__(self): #在执行__init__方法有一个方法在帮你创造self print('in init function') self.x = 1 def __new__(cls, *args, **kwargs):#先执行__new__方法 print('in new function') return object.__new__(A, *args, **kwargs) a = A() b = A() c = A() d = A()
单例模式
class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls, *args, **kw) return cls._instance one = Singleton() two = Singleton() print(one,two) one.name = 'alex' print(two.name)
__call__方法
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __call__(self, *args, **kwargs): print(123) Foo()()
__len__
class Foo: def __len__(self): return len(self.__dict__) def __hash__(self): print('my hash func') return hash(self.name) f = Foo() print(len(f)) f.name = 'egon' print(len(f)) print(hash(f))
__hash__与__eq__ set方法依赖__hash__和__eq__这两个内置方法
#留下同样名字和性别的对象 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))
纸牌游戏
from collections import namedtuple Card = namedtuple('Card',['rank','suit']) #每一个card的对象就是一张纸牌 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 def __call__(self, *args, **kwargs): return self._cards deck = FranchDeck() print(deck[0]) print(deck[3]) print(deck[2]) print(deck[1])
# from random import shuffle #shuffle可以打乱顺序
# shuffle(deck)#洗牌
# print(deck())
# shuffle(deck)
# print(deck())#洗牌
5 logging
通过config来配置只能选择一种输出模式
import logging #config只能写文件里或者打印在屏幕上2个选择一个 # logging.basicConfig( # level=logging.DEBUG, # format = '%(name)s %(asctime)s [%(lineno)d] -- %(message)s',#需要输出的内容 # datefmt = '%d/%m/%y %H:%M:%S',#日期格式 # filename = 'logging_info'#如果出现它那就是要要把内容放在文件里不会打印到屏幕上 # ) # logging.debug("debug") # logging.info("info") # logging.warning("出错了")
logger可以输出屏幕和写入文件
# logger对象可以选择打印或者写在文件里 import logging def my_logger(filename,file=True,stream = True): logger = logging.getLogger() formatter = logging.Formatter(fmt='%(name)s %(asctime)s [%(lineno)d] -- %(message)s', datefmt='%d/%m/%y %H:%M:%S')#指定打印的格式和数据 logger.setLevel(logging.DEBUG) #指定日志打印的等级 if file: file_handler = logging.FileHandler(filename,encoding='utf-8')#格式 file_handler.setFormatter(formatter) # 文件流 文件操作符 logger.addHandler(file_handler) if stream: stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) #屏幕流 屏幕操作符 logger.addHandler(stream_handler) return logger logger = my_logger('logging') logger.warning("出错了") logger.debug("debug")
推荐使用logger
6异常处理
架构
try: pass except ValueError: pass except Exception as e: print('统筹处理所有错误的措施') else: print("针对这段try中的代码没有异常要特别处理的") finally: print("不管有没有异常都要执行的代码")
7hashlib摘要算法
import hashlib md5_obj = hashlib.md5('nezha'.encode('utf-8'))#加盐啦 md5_obj.update('123456'.encode('utf-8')) print(md5_obj.hexdigest()) md5_obj.update('hello,egon~'.encode('utf-8')) print(md5_obj.hexdigest())
主要用途:
# 文件校验
# 文件是否被改变
# 登录密码
# 不能解密,但可以“撞库”
# 加盐 hashlib.md5('nezha'.encode('utf-8'))
给文件加密
import hashlib md5_obj = hashlib.md5() import os filesize = os.path.getsize('filename')#需要自己创建一个文件 f = open('filename','rb') while filesize>0: if filesize > 1024: content = f.read(1024) filesize -= 1024 else: content = f.read(filesize) filesize -= filesize md5_obj.update(content) # for line in f:#这是另一个加密的方式 # md5_obj.update(line.encode('utf-8'))#这两种不同的加密方式得到的结果是一样的 md5_obj.hexdigest()