面向对象进阶

isinstance和issubclass
isinstance() :判断一个对象是不是这个类的实例,如果这个类有父类,那么这个对象也是其父类的对象
issubclass() : 判断两个类是不是父子关系,接受两个参数(子类,父类)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

class Foo:
    pass

s=Foo()
print(isinstance(s,Foo))     #True

issubclass(sub, super)检查sub类是否是 super 类的派生类 

class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
print(issubclass(Bar, Foo))     #True

 

反射

反射: 把一个字符串数据类型的变量变成一个真实存在在这个程序中的变量名,并且能够使用它

python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

#-对象中的反射
class
Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #检测是否含有某属性和方法 print(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73} print(hasattr(obj,'name')) #True print(hasattr(obj,'say_hi')) #True print(hasattr(obj,'aaa')) #False #获取属性 n=getattr(obj,'name') # = obj.name print(n) # egon n= obj.name print(n) # egon func=getattr(obj,'say_hi') print(func) # <bound method Foo.say_hi of <__main__.Foo object at 0x0000000001E805F8>> func() # hi,egon func=getattr(obj,'aaa','bbb') print(func) # bbb #设置属性 setattr(obj,'sb',True) #obj.sb=True print(obj.sb) #True print(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73, 'sb': True} setattr(obj,'show_name',lambda self:self.name+'sb') # obj.show_name() print(obj.show_name(obj)) # egonsb print(obj.__dict__) # {'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x0000000001D13E18>} #删除属性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,则报错
#-类中的反射
class
Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) print(Foo.__dict__) #{'__module__': '__main__', 'f': '类的静态变量', '__init__': <function Foo.__init__ at 0x00000000029D5BF8>, # 'say_hi': <function Foo.say_hi at 0x00000000029D5C80>, '__dict__': <attribute '__dict__' of 'Foo' objects>, # '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None} print(hasattr(Foo,'f')) # True print(getattr(Foo,'say_hi')) # <function Foo.say_hi at 0x00000000029D5C80> getattr(Foo,'say_hi')() #会报错 如果传个实例化对象就不会 getattr(Foo,'say_hi')(obj) # hi,egon setattr(Foo,'a','abc') # Foo.a='abc' print(Foo.__dict__) # 最后多了一个 'a': 'abc' print(Foo.a) # abc delattr(Foo,'a') delattr(Foo,'say_hi') delattr(Foo,'f') print(Foo.__dict__) # {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000029E5BF8>, # '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
#-类中的反射与类方法,静态方法结合使用
class
Foo(object): staticField = "old boy" def __init__(self): self.name = 'wupeiqi' @classmethod def func(cls): return cls.staticField @classmethod def func1(cls,a): return a+cls.staticField @staticmethod def bar(): return 'bar' a='a' print(Foo.staticField) # old boy print(getattr(Foo, 'staticField')) # old boy print(getattr(Foo, 'bar')()) # bar 调用静态方法 print(getattr(Foo, 'func')()) # old boy 调用类中方法 print(getattr(Foo, 'func1')(a)) # aold boy 调用类方法,并往其中传参
#-当前模块的反射
import
sys def s1(): print ('s1') def s2(): print ('s2')
xiaoxuanxuan = 2222
this_module = sys.modules[__name__]             # 在自己文件中__name__会变成__main__ 自身文件的模块名 用模块名.属性或方法查看  
print(getattr(this_module, 'xiaoxuanxuan')) #22222
print
(hasattr(this_module, 's1')) # True
getattr(this_module, 's2')() # s2
#导入其他模块,利用反射查找该模块是否存在某个方法
# module_test.py与index.py在同一目录下
# 在module_test.py中
def test():
    print('from the test')

# 在index.py中
import module_test as obj

print(hasattr(obj,'test'))   # True
getattr(obj,'test')()       #  from the test

 

__str__和__repr__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type

    def __repr__(self):
        return 'School(%s,%s)' %(self.name,self.addr)
    # def __str__(self):
    #     return '(%s,%s)' %(self.name,self.addr)
s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))    #  from repr:  School(oldboy1,北京)
print('from str: ',str(s1))      #  from repr:  School(oldboy1,北京)
print(s1)                        #  School(oldboy1,北京)
class B:

     def __str__(self):
         return 'str : class B'

     def __repr__(self):
         return 'repr : class B'


b=B()
print('%s'%b)            # str : class B
print('%r'%b) # repr : class B
class Animal:
    def __init__(self,kind,name):
        self.kind = kind
        self.name = name

    def __str__(self):
        return 'str : %s : %s'%(self.kind,self.name)

    def __repr__(self):
        return 'repr : %s : %s'%(self.kind,self.name)
cat = Animal('cat','guolei')
print('%s'%cat)      #  str : cat : guolei
print('%r'%cat)      #  repr : cat : guolei
print(str(cat))        #   str : cat : guolei
print(repr(cat))      #   repr : cat : guolei

 

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 __repr__(self):
        return 'School(%s,%s)' %(self.name,self.addr)
    def __str__(self):
        return '(%s,%s)' %(self.name,self.addr)

    def __format__(self, format_spec):
        # if format_spec
        if not format_spec or format_spec not in format_dict:
            format_spec='nat'
        fmt=format_dict[format_spec]
        # obj=self
        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')
print(format(s1,'nat'))            #  oldboy1-北京-私立


 

__del__

析构方法,当对象在内存中被释放时,自动触发执行。 或者使用 del 对象  自动触发类中__del__

class Foo:

    def __del__(self):
        print('执行我啦')

f1=Foo()
del f1
print('------->')

#输出结果
执行我啦
------->

 

class A:
    def __del__(self):
        print('aaa')

class B:
    def __del__(self):
        print('bbb')
a=A()
b = B()
print('ccc')    
#输出
ccc
aaa
bbb

 

 

item系列

__getitem__\__setitem__\__delitem__

class Animal:
    def __init__(self,name):
        self.name = name

    def __getitem__(self, item):
        return getattr(self,item)

    def __setitem__(self, key, value):
        setattr(self,key,value)

    def __delitem__(self, key):
        delattr(self,key)
cat = Animal('guolei')
print(cat['name'])    #去类中找getitem方法   guolei
cat['sex'] = '' #去类中找setitem方法
print(cat.sex) #
print(cat['sex']) #公  
print(cat.__dict__) #{'name': 'guolei', 'sex': '公'}
del
cat['name'] # 去类中找delattr方法
print(cat.__dict__) #{'sex': '公'}

 

__new__

单例模式 实例始终只有一个 他的属性可以随着你的改变而改变

#正常情况下,示例化后先进行__new__方法,在父类object方法中new出一个新对象,给予__init__方法中的self,这就是正常情况下实例化对象的步骤
#即先去元祖那里,创建一个人(裸体的人),再为这个人穿衣服(在__init__方法中的self实例化)
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)
#输出:
in new function
in init function
1
class Singleton:
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(Singleton, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance

one = Singleton()
two = Singleton()

two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)
class Teacher:               #创建一个老师类
    __isinstance = None      #创建一个私有静态变量来装裸着的对象
    def __new__(cls, *args, **kwargs):   #创建一个裸着的对象
        if not cls.__isinstance:         #如果__isinstance属性为None
            cls.__isinstance = object.__new__(cls)   #用object.__new__创建一个裸着的对象
        return cls.__isinstance          #返回一个对象

    def __init__(self,name,cloth):       #self就是cls.__isinstance返回的对象
        self.name = name                 #给self的name属性赋值
        self.cloth = cloth               #给self的cloth属性赋值

刘老师 = Teacher('刘永熹','白色')
print(刘老师.name,刘老师.cloth)     #  刘永熹 白色
王老师 = Teacher('王庆帅','黑色')
print(刘老师.name,刘老师.cloth)     # 王庆帅 黑色
print(王老师.name,王老师.cloth)     #  王庆帅 黑色
print(刘老师,王老师)   #<__main__.Teacher object at 0x00000000027C0630> <__main__.Teacher object at 0x00000000027C0630>

 

__call__

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print('__call__')


obj = Foo() # 执行 __init__
obj()       # 执行 __call__

 

__len__

对于 __len__ 方法的执行是由len(对象)后触发的,即: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
print(a.__dict__) # {'a': 1, 'b': 2}

 

__hash__

对于 __hash__ 方法的执行是由hash(对象)后触发的,即: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))     # -7422275419112235454   每次运行都不相同


 

__eq__

对于 __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

 

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])

 

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[0])     #  第一张   Card(rank='2', suit='红心')
from random import choice
print(choice(deck))   #随机抽一张    Card(rank='2', suit='黑桃')
print(choice(deck))   #随机抽一张    Card(rank='A', suit='梅花')

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))   # 只有一个对象,set()方法运行了类中的__hash__与__eq__方法
面试题,一百个对象中去重


 

 

posted @ 2017-09-24 10:32  JAYWX  阅读(155)  评论(0编辑  收藏  举报