zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    单源最短路径-邻接表无向网络
    带权邻接表图的最小生成树
    邻接矩阵有向图的广度优先遍历
    邻接表无向图的深度优先遍历
    图基础-创造用于测试的简单图
    用EFCore从mssql数据库生成实体类
    使用EF Core访问SqlServer数据库
    哈夫曼树综合练习
    树形结构例--控制台显示文件夹结构
    Java之设计模式
  • 原文地址:https://www.cnblogs.com/qflyue/p/8330601.html
Copyright © 2011-2022 走看看