面向对象进阶

目录

isinstance和issubclass

反射

__str__和__repr__

__del__

item系列

__new__

__call__

__len__

__eq__


  • isinstance和issubclass

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

class Foo(object):pass
obj = Foo()
print(isinstance(obj, Foo))
'''
结果:True
'''

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

class Foo(object):pass
 
class Bar(Foo):pass
 
print(issubclass(Bar, Foo))
'''
结果:True
'''
  • 反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

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

四个可以实现自省的函数

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

# 反射对象中的属性和方法   hasattr getattr setattr delattr
class A():
    a = '类的静态变量'
    @classmethod
    def func(cls):
        print('in func')

# hasattr getattr用法
print(getattr(A,'a'))  # 反射对象的属性
print(getattr(A,'func'))  # 反射类的方法,打印是个内在地址,加上()调用函数
getattr(A,'func')()  #输出in func

# hasattr检测是否含有某属性,一般和getattr一起使用
if hasattr(A,'func'):  #注意hasattr和getattr参数一样
    getattr(A,'func')

#反射模块的属性和方法
"""
程序目录:
    my.py
    index.py
    
my.py代码:
day = 'Monday' 
def wahaha():
    print('wahahaha')
class C:pass

当前文件:
    index.py

"""
import my
print(getattr(my,'day')) # 反射模块的属性
getattr(my,'wahaha')()   # 反射模块的方法
print(getattr(my,'C')())  # 反射模块的类

#内置模块也能用
import time
print(getattr(time,'time')())
print(getattr(time,'asctime')())
# 要反射的函数有参数怎么办?
print(time.strftime('%Y-%m-%d %H:%M:S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))  #反射的函数有参数

#反射当前模块成员
import sys
abc = 1
def aa():
    print('aaaaa')
print(sys.modules['__main__'])  #当前模块
print(getattr(sys.modules['__main__'],'abc'))  # 反射自己模块中的变量
getattr(sys.modules['__main__'],'aa')()   # 反射自己模块中的函数


# setattr  设置修改变量
class B:
    pass
b = B()
setattr(b, 'name', 'bbb')
setattr(B, 'name', 'BBB')
print(B.name)
print(b.name)

# delattr 删除一个变量
delattr(b, 'name')
print(b.name)
delattr(B, 'name')
print(b.name)  #报错

  • __str__和__repr__

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

自定制格式化字符串__format__

#_*_coding:utf-8_*_

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]
        return fmt.format(obj=self)

s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)

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

%s和%r

class B:

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

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


b=B()
print('%s'%b)
print('%r'%b)
  • __del__

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

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

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

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

'''
输出结果:
执行我啦
------->
'''
  • item系列

__getitem__\__setitem__\__delitem__

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

    def __getitem__(self, item):   #查
        if hasattr(self,item):
            return self.__dict__[item]

    def __setitem__(self, key, value):   #改
       self.__dict__[key] = value

    def __delitem__(self, key):  #删
        del self.__dict__[key]

#对象通过__getitem__\__setitem__\__delitem__方法来现实像dict(字典)一样通过ke来增删改查
f = Foo('a',18)
print(f['name'])
f['age'] = 20
print(f.__dict__)

f['name'] = 'b'
print(f['name'])
print(f.__dict__)

del f['name']
print(f.__dict__)

'''
结果:
a
{'name': 'a', 'age': 20}
b
{'name': 'b', 'age': 20}
{'age': 20}

'''
  • __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)
'''
结果:
in new function
in init function
1
'''
#单例模式
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()

two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 41749696
print(id(two))
# 41749696
print(one == two)
# True
print(one is two)
# True
  • __call__

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

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

class Foo:

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

        print('__call__')


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

class Foo:
    def __init__(self):
        self.a = 1
        self.b = 2
        self.c = 3

    def __len__(self):
        return len(self.__dict__)

F = Foo()
print(len(F))
  • __eq__

    class Foo:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self, other):
            if self.__dict__ == other.__dict__:
                return True
            else:
                return False
    
    
    F = Foo()
    f = Foo()
    print(F == f)  #True
    print(F.a == f.a)   #True
    print(F.a == f.b)   #False
    

    去重面试题

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

     

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值