python之路--面向对象之反射
isinstance和issubclass
isinstance(对象,类)判断一个对象是不是这个类的对象
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
# 判断一个类是不是另一个类的子类,传两个参数(子类,父类)
print(issubclass(Son,Foo))
print(issubclass(Son,Foo))
print(issubclass(Son,object))
print(issubclass(Foo,object))
print(issubclass(int,object))
staticmethod和classmethod
相同点
都可以直接被类调用,不需要实例化
不同点
- 类方法必须一个cls参数表示这个类
- 静态方法不需要,静态方法不能直接使用
绑定方法
普通方法:默认有一个self对象传进来,并且只能被对象调用 --绑定到对象
类方法:默认有一个cls传进来表示被类,并且可以被类和对象调用(不推荐) --绑定到类
非绑定方法
静态方法:没有默认参数,并且可以被类和对象调用(不推荐) --非绑定
class Student:
title = 'hello world'
def __int__(self):pass
@staticmethod # 静态方法 :让类的方法正常被调用,就像正常的函数一样
def show_student_info():
print('小明 男')
@classmethod # 类方法:默认参数cls,可以直接用类名调用,可以和类属性交互
def hello(cls):
print(cls.title)
Student.show_student_info()
s = Student()
s.show_student_info()
s.hello()
反射
什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
python面向对象中的反射
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中一切皆对象(都可以使用反射)
实现反射的4个函数
常用
hasattr
getattr
不常用
setattr
delattr
对象反射
# 对象反射
class Foo:
def __init__(self):
self.name = 'egon'
self.age = 73
def func(self):
print(123)
# 反射 可以用字符串的方式去访问对象的属性、调用对象的方法
egg = Foo()
print(hasattr(egg,'name')) # 判断属性时候,存在与否都返回布尔值
print(getattr(egg,'name')) # 得到该属性的值
print(getattr(egg,'func')) # 判断方法时,存在返回内存地址,不存在报错
func = getattr(egg,'func') # 把内存地址重新赋值给变量func
func() # 加括号直接调用
setattr(egg,'sex','nv')
print(egg.sex)
setattr(egg,'show_name',lambda self:self.name + 'sb')
print(egg.show_name(egg))
delattr(egg,'name')
print(egg.name)
类反射
class Foo:
f = 456
@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'))
getattr(my_module,'test')()
def demo1():
print('demo1')
# 在本模块中应用反射
import sys
module_obj = sys.modules[__name__]
print(hasattr(module_obj,'demo1'))
模块反射关联文件(同级目录下的my_module)
def test():
print('test')
内置方法
__str__和__repr__
- 当打印一个对象的时候,如果实现了__str__,打印其中的返回值
- 当__str__没有被实现的时候,就会调用__repr__
- 当用字符串格式化的时候%s和%r会分别帝欧用对应的__str__和__repr__
- 不管是在字符串格式化的时候还是在打印对象的时候,__repr__都可以作为__str__的替补,反之不是
- 如果__str__和__repr__方法你只能实现一个,先实现__repr__
- 必须要有return return的对象必须是字符串
class Foo:
def __init__(self,name):
self.name = name
def __str__(self):
return 'obj info in str'
def __repr__(self):
return 'obj info in repr'
f = Foo('8192bit')
print('%s'%f)
print('%r'%f)
print(repr(f)) # 等于f.__repr__()
print(str(f))
__format__
# 自定制 __format__
format_dict = {
"nat": '{obj.name}-{obj.address}-{obj.type}',
"nta": '{obj.name}:{obj.address}:{obj.type}',
"tan": '{obj.name}/{obj.address}/{obj.type}',
}
class School:
def __init__(self,name,address,type):
self.name = name
self.address = address
self.type = type
def __str__(self):
return "school_name:%s,school_address:%s"%(self.name,self.address)
def __repr__(self):
return "school(%s,%s)"%(self.name,self.type)
def __format__(self, format_spec):
if not format_spec or format_spec not in format_dict:
format_spec = "nat"
return format_dict[format_spec].format(obj=self)
s = School('oldboy','北京','私立')
print('%s'%s)
print('%r'%s)
print(format(s,'nat'))
print(format(s,'nta'))
print(format(s,'tan'))
print(format(s,'nataaaaaaaaaa'))
__del__
析构方法,当对象在内存被释放时,自动触发执行。
注:此方法一般无需定义,以为Python是一门高级语言,程序员在使用时无序关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:
def __del__(self):
print('执行我啦')
f= Foo()
print(123)
print(123)
print(123)
del f # 默认最后执行,本次为指定执行
print(123)
print(123)
item 系列(__getitem__,__setitem__,__delitem__)
class Foo:
def __init__(self):
self.name = '8192bit'
self.age = 18
def __getitem__(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
f = Foo()
print(f['name'])
f['sex'] = 'nv'
print(f['sex'])
del f['sex']
__new__
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A,*args,**kwargs)
a = A()
print(a.x)
实现单例模式
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()
three = Singleton()
go = Singleton()
print(one,two)
one.name = 'alex'
print(two.name)
__call__
对象名后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
__len__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
__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))
__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)
纸牌游戏
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 choice # 随机拿牌
# print(choice(deck))
# print(choice(deck))
from random import shuffle # 洗牌
shuffle(deck)
print(deck())
shuffle(deck)
print(deck())
面试题
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))