面向对象进阶

一、isinstance和issubclass

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

class Foo(object):
     pass
  
obj = Foo()
  
isinstance(obj, Foo)

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

class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
issubclass(Bar, Foo)

二、反射

setattr:设置类或对象的属性

class Cdemo:
    dic = "静态属性"

    @classmethod
    def func1(cls):
        print('这个是个类方法')

    def func2(self):
        print('这是个对象方法')

obj = Cdemo()

setattr(obj,'sb',True)
setattr(obj,'new_func',lambda self:print('新建的方法'))
print(obj.__dict__)
print(obj.new_func(obj))

delattr:删除类或对象的属性

class Cdemo:
    dic = "静态属性"

    @classmethod
    def func1(cls):
        print('这个是个类方法')

    def func2(self):
        print('这是个对象方法')

obj = Cdemo()
#删除属性
delattr(Cdemo,'dic')
delattr(Cdemo,'func1')
delattr(Cdemo,'func3')#不存在,则报错

getattr:获取类或对象的属性

oss = '123456'

import sys
print(sys.modules['__main__']) # <module '__main__' from 'H:/PythonDemo/Demo_PythonBook/python_class/s10.py'>
local_models = getattr(sys.modules['__main__'],'oss')
print(local_models) # 123456
反射自己模块的东西
class Cdemo:
    dic = "静态属性"

    @classmethod
    def func1(cls):
        print('这个是个类方法')

    def func2(self):
        print('这是个对象方法')

# 静态属性的getattr()操作
ret = getattr(Cdemo,'dic')
print(ret)
# 类方法的getattr()操作
ret1 = getattr(Cdemo,'func1')
print(ret1())
# 类对象的getattr()操作
c = Cdemo()
ret2 = getattr(c,'func2')
print(ret2())

hasattr:检查类或对象是否有该属性

class Cdemo:
    dic = "静态属性"

    @classmethod
    def func1(cls):
        print('这个是个类方法')

    def func2(self):
        print('这是个对象方法')

ret = hasattr(Cdemo,'dic') # 是否有静态属性,返回True或False
print(ret)
ret = hasattr(Cdemo,'func1') # 是否有类方法,返回True或False
print(ret)

obj = Cdemo()
ret = hasattr(obj,'func1') # 是否有对象方法,返回True或False
print(ret)

 三、内置方法

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

# __str__和__repr__

class A:
    def __str__(self):
        """
        可用于对象说明
        :return:
        """
        return 'A'

a = A()
# 打印一个对象的时候就是调用__str__()
# __str__() 默认返回内存地址的字符串,可以使用此方法重新定义返回值
print(a)


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

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


b = B()
# 如果__str__没有被定义,那么就会使用__repr__来代替输出
# 注意:这俩方法的返回值必须是字符串,否则抛出异常
print('%s' % b)
print('%r' % b)
__str__和__repr__

2)__del__:析构方法,当对象在内存中被释放时,自动触发执行。

class Foo:
    def __init__(self,filepath):
        self.filepath = filepath
        self.f = open(self.filepath, 'w')
    # 在删除一个对象前进行剩余的收尾工作
    # 比如当打开一个文件,删除了对象,内存消失了,但是文本依然打开着,所以需要进行收尾来及时释放内存
    def __del__(self):
        print("执行关闭")
        self.f.close()

    def open_file(self):
        self.f.write("1111")

f1=Foo('ceshi.txt')
print(f1.open_file())
__del__

3)__len__:计算长度

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a))
__len__

4)__call__:一个对象+()则执行__call__方法,可以给对象设置一些功能

class A:
    def __init__(self,name):
        pass
    def __call__(self, *args, **kwargs):
        print("执行我了")

# 一个对象+()相当于执行__call__方法
a = A('alex')
a()
__call__

 5)__new__,__init__:__new__构造方法,创建一个对象self;__init__初始化方法

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)

# 执行顺序:__new__ --- __init__  ---  print(a.x)
# 输出结果:
'''
in new function
in init function
1
'''
a = A()
print(a.x)
__new__
#单例模式是23种设计模式中的一种,只依靠修改对象属性来实现一个类只能创建一个对象的更多实用操作
class A:
    __instance = False

    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __new__(cls,*args,**kwargs):
        if cls.__instance:
            return cls.__instance
        cls.__instance = object.__new__(cls)
        return cls.__instance

a = A('aaa',18)
b = A('bbb',28)
print(a)
print(b)

print(a.name)
print(b.name)
单例模式(设计模式)

6)__eq__:判断对象是否相等

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

    def __eq__(self, other):
        # self, other默认这两个参数为内存地址
        if self.name == other.name:
            return True
        return False

a1 = A('jack')
a2 = A('jack')

print(a1 == a2)
__eq__

7)__hash__:自定义hash值

class A:
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def __hash__(self):
        return hash(self.a + self.b)

a1 = A('111','222')
a2 = A('111','222')
# 如果没有写__hash__()默认使用内存地址进行hash,hash值肯定不同
print(hash(a1)) #-7735806094895007429
print(hash(a2)) #-7735806094895007429
__hash__

 四、补充

import json
from collections import namedtuple
Card = namedtuple('Card',['rank','suit'])  # rank牌面大小  suit牌面花色
# c1 = Card(rank=2,suit='红心')

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

    def __init__(self):
        '''
            for suit in FranchDeck.suits
                for rank in FranchDeck.ranks
                    Card(suit,rank)
        '''
        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 __str__(self):
        return json.dumps(self._cards,ensure_ascii=False)

deck = FranchDeck()
# 随机抽两张牌
from random import choice  # 依赖内置__len__()方法
print(choice(deck))
print(choice(deck))
# 洗牌
from random import shuffle # 依赖内置__setitem__()方法
shuffle(deck)
print(deck[:5])
# __str__查看对象内容
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))  # set 依赖__hash__和__eq__
某人每年都参与登记,每次登记时间不同的例子

 

posted @ 2019-03-28 17:15  我在地球凑人数的日子  阅读(76)  评论(0编辑  收藏  举报