python面向对象进阶

前言

上节大话python面向对象对面向对象有了一些了解,这次就不用大话风格了          (ps:真心不好扯啊)

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)

python 反射

1 什么是反射

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

2 python面向对象中的反射:

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

反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员

下面逐一介绍

 1 class Foo:
 2     def __init__(self):
 3 
 4         self.name='python反射'
 5 
 6     def func(self):
 7 
 8         print("这是一个func方法")
 9 
10 # getattr获取成员
11 obj=Foo()
12 
13 ret=getattr(obj,'name')
14 
15 print(ret)#输出   python反射
16 
17 # hasattr检查成员
18 
19 ret=hasattr(obj,'name')
20 print(ret) #输出 True
21 
22 # setattr设置成员
23 
24 setattr(obj,'name','new python反射')
25 
26 print(obj.name)#输出  new python反射
27 
28 # delattr删除成员
29 
30 delattr(obj,'name')
31 
32 print(obj.name)#报错  AttributeError: 'Foo' object has no attribute 'name'

__str__与__repr__

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

__repr__和__str__这两个方法都是用于显示的,__str__是面向用户的,而__repr__面向程序员。

  • 打印操作会首先尝试__str__和str内置函数(print运行的内部等价形式),它通常应该返回一个友好的显示。

  • __repr__用于所有其他的环境中:用于交互模式下提示回应以及repr函数,如果没有使用__str__,会使用print和str。它通常应该返回一个编码字符串,可以用来重新创建对象,或者给开发者详细的显示。

区别:

class Foo:
    def __init__(self):

        self.name='python反射'

    def __repr__(self):
        return "这是一个repr方法"
    def __str__(self):
        return "这是一个str方法"

print(Foo())

class Foo:
    def __init__(self):

        self.name='python反射'

    def __repr__(self):
        return "这是一个repr方法"
    # def __str__(self):
    #     return "这是一个str方法"

print(Foo())

也就是说,在__str__不存在的情况下,print会直接使用__repr__返回的值。当我们想所有环境下都统一显示的话,可以重构__repr__方法;当我们想在不同环境下支持不同的显示,例如终端用户显示使用__str__,而程序员在开发期间则使用底层的__repr__来显示,实际上__str__只是覆盖了__repr__以得到更友好的用户显示。

以下几种情况会触发__repr__与__str__的调用 ,%s格式化字符串,print输出,str()

__del__

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

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

class Foo:
    def __init__(self):

        self.name='python反射'

    def __del__(self):
        print("我是析构函数")

Foo()

__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']=2
del f1.age1
del f1['age']
f1['name']='item系列'
print(f1.__dict__)

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

单例模式

__call__

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

class Foo:
    def __init__(self):
        self.name='__call__方法'


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

        print("调用call方法")


Foo()()#输出   调用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))

__eq__ 与 __hash__

遇到了一次关于这哥俩的面试题,就把他放一块吧

题目是这样的:一百个对象去重,如果name与gender相同就代表两对象相同(类似于java的重写equal)

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

    def __hash__(self):
        return hash(self.name+self.gender)

    def __eq__(self, other):
        if self.name == other.name and self.gender == other.gender:return True

    def __str__(self):
        return self.name

p_lst=[Person('python',20,''),Person('python',18,''),Person('linux',20,'')]

ret=set(p_lst)#   多方便,重写这仨哥们就完事了
for i in ret:
    print(i)
原文地址:https://www.cnblogs.com/qflyue/p/8330601.html