python之路_面向对象进阶

一、内置函数isinstance和issubclass

1、isinstance()

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

class Foo(object):
    pass
obj = Foo()
print(isinstance(obj, Foo))      #输出结果:True

print(isinstance(10,int))        #输出结果:True

  sinstance() 与 type() 区别:type() 不会认为子类是一种父类类型,不考虑继承关系。sinstance() 会认为子类是一种父类类型,考虑继承关系。

class A:
    pass
class B(A):
    pass
isinstance(A(), A)              # returns True
type(A()) == A                  # returns True
isinstance(B(), A)              # returns True
type(B()) == A                  # returns False

(2)issubclass()

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

class Foo(object):
    pass
class Bar(Foo):
    pass
print(issubclass(Bar, Foo))    #输出结果:True

二、反射相关

  python面向对象中的反射:通过字符串的形式操作对象相关的属性。如下为4个可以实现自省的函数:

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(hasattr(obj,'name'))     #输出结果:True
print(hasattr(obj,'say_hi'))             #输出结果:True

#获取属性
n=getattr(obj,'name')
print(n)                                 #输出结果:egon
func=getattr(obj,'say_hi')
func()                                   #输出结果:hi,egon


#设置属性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)                      #输出结果:{'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x00000194A8817048>}
print(obj.show_name(obj))

#删除属性
delattr(obj,'age')
delattr(obj,'show_name')

print(obj.__dict__)                      #输出结果:{'name': 'egon', 'sb': True}

 三、类的内置方法

1、__str__和__repr__

  改变对象的字符串显示__str__,__repr__,这俩方法的返回值必须是字符串,否则抛出异常。

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(str(cat))                               #输出结果:str : cat : guolei
print(repr(cat))                              #输出结果:repr : cat : guolei
print('%s'%cat)                               #输出结果:str : cat : guolei
print('%r'%cat)                               #输出结果:repr : cat : guolei

 2、__del__

  析构方法,当对象在内存中被释放时,自动触发执行。注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:

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

f1=Foo()
del f1                                        #输出结果:执行我啦

3、__getitem__\__setitem__\__delitem__

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['age1']=19
del f1.age1                                          #输出结果:del obj.key时,我执行
del f1['age']                                        #输出结果:del obj[key]时,我执行
f1['name']='alex'
print(f1.__dict__)                                   #输出结果:{'name': 'alex'}

4、__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)

单例模式:

  无论实例化多少个对象,只有一个对象存在,且这个对象为最后实例化的那个对象。

#实例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)                                       # True
class Teacher:
    __instance=None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance=object.__new__(cls)
        return cls.__instance
    def __init__(self,name,cloth):
        self.name=name
        self.cloth=cloth
刘老师=Teacher('liu','bai')
王老师=Teacher('wang','hei')
print(刘老师.name)                                     #输出结果:wang
print(刘老师.cloth)                                    #输出结果:cloth

5、__call__

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

class Foo:
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs):
        print('__call__')
obj = Foo()                                         # 执行 __init__
obj()                                               # 执行 __call__

6、__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

7、__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))                                    #输出结果:3429960989477292991

8、

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

四、相关例题

1、纸牌游戏1:抽牌

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]

deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))

2、纸牌游戏2:洗牌

class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [(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 shuffle
shuffle(deck)
print(deck[:5])

3、一道面试题

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

 

posted @ 2017-09-23 23:17  骑猪走秀  阅读(178)  评论(0编辑  收藏  举报