zoukankan      html  css  js  c++  java
  • 面向对象——进阶

    检查实例化对象与派生类

    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)
    复制代码

    反射

    1 什么是反射

      反射:是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)

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

    四个可以实现自省的函数

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

    对象

    复制代码
    def hasattr(*args, **kwargs): # real signature unknown
        """
        Return whether the object has an attribute with the given name.
        
        This is done by calling getattr(obj, name) and catching AttributeError.
        """
        pass
    复制代码
    复制代码
    def getattr(object, name, default=None): # known special case of getattr
        """
        getattr(object, name[, default]) -> value
        
        Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
        When a default argument is given, it is returned when the attribute doesn't
        exist; without it, an exception is raised in that case.
        """
        pass
    复制代码
    复制代码
    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
        
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass
    复制代码
    复制代码
    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
        
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass
    复制代码
    复制代码
    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'))
    print(hasattr(obj,'say_hi'))
    
    #获取属性
    n=getattr(obj,'name')
    print(n)
    func=getattr(obj,'say_hi')
    func()
    
    print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
    
    #设置属性
    setattr(obj,'sb',True)
    setattr(obj,'show_name',lambda self:self.name+'sb')
    print(obj.__dict__)
    print(obj.show_name(obj))
    
    #删除属性
    delattr(obj,'age')
    delattr(obj,'show_name')
    delattr(obj,'show_name111')#不存在,则报错
    
    print(obj.__dict__)
    复制代码

    复制代码
    class Foo(object):
     
        staticField = "old boy"
     
        def __init__(self):
            self.name = 'wupeiqi'
     
        def func(self):
            return 'func'
     
        @staticmethod
        def bar():
            return 'bar'
     
    print getattr(Foo, 'staticField')
    print getattr(Foo, 'func')
    print getattr(Foo, 'bar')
    复制代码

    反射当前模块成员

    复制代码
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import sys
    
    
    def s1():
        print 's1'
    
    
    def s2():
        print 's2'
    
    
    this_module = sys.modules[__name__]
    
    hasattr(this_module, 's1')
    getattr(this_module, 's2')
    复制代码
     
     
     

    导入其他模块,利用反射查找该模块是否存在某个方法

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    def test():
        print('from the test')
    复制代码
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    """
    程序目录:
        module_test.py
        index.py
     
    当前文件:
        index.py
    """
    
    import module_test as obj
    
    #obj.test()
    
    print(hasattr(obj,'test'))
    
    getattr(obj,'test')()
    复制代码

    反射的增删改查

    # getattr一定要和hasattr配合使用
    
    # 反射 4个内置函数
    # getattr ******
    # hasattr ******
    # setattr # 修改和新建 **
    # delattr # 删除一个属性 *
    
    # 增删改 对象属性
    # class A:
    # def __init__(self,name):
    # self.name = name
    #
    # def wahaha(self):
    # print('wahahahahaha')
    #
    # a = A('alex')
    # a.name
    # a.wahaha()
    # getattr(a,'name')
    # # a 'age' = 18
    # # a.age = 18
    # print(a.__dict__)
    # setattr(a,'age',18) # 给a对象新增一个属性
    # print(a.__dict__)
    # setattr(a,'name','egon')
    # print(a.__dict__)
    #
    # # del a.age
    # delattr(a,'age')
    # print(a.__dict__)
    
    
    # 增删改 方法
    class A:
       def __init__(self,name):
       self.name = name
    
       def wahaha(self):
       print('wahahahahaha')
    
       def qqxing(self):
       print('qqqqqxing')
    
       a = A('alex')
       setattr(A,'qqxing',qqxing)
       setattr(a,'qqxing',qqxing)
       print(a.__dict__)
       a.qqxing(a)

    双下方法

    一。 内置函数 
    1.__len__ 与 len()


    # class A:
    # def __init__(self,name,age,sex,cls):
    # self.name = name
    # self.age = age
    # self.sex = sex
    # self.cls = cls
    # def __len__(self):
    # return len(self.__dict__)
    #
    # # 有一个内置函数 和内置方法len()是唯一对应的关系
    # a1 = A('alex',81,'不详',2)
    # a1.hobby = '烫头'
    # a2 = A('egon',20,'不详',3)
    # a3 = A('yuan',21,'不详',4)
    # print(len(a1))
    # print(len(a2))
    # print(len(a3))



    2.字典的存储
    # hash

    class A:
    def __init__(self,name,age,sex,cls):
    self.name = name
    self.age = age
    self.sex = sex
    self.cls = cls
    def __hash__(self):
    return 0
    a1 = A('alex',81,'不详',2)
    print(hash(a1))
    每一次的哈希值都不同,为什么可以直接哈希,因为object类里有__hash__方法
     

    二。__str__ 与 __repr__  与  print()

    ps: 总结:

      1.print() 想文件中写,print() 替你将数据类型转化成字符串打印出来

      2.__str__ :  object 类中的__str__ 就是返回一个数据类型的内存地址

    复制代码
    l = [1,2,3,4]
    print(l)   # 向文件中写   print替你将数据类型转化成字符串打印出来
    
    class List:
        def __init__(self,*args): 5
            self.l = list(args)
        def __str__(self):
            return '[%s]'%(','.join([str(i) for i in self.l]))
    l = List(1,2,3,4,5)
    print(l)   #--> l.__str__()   # object类中的__str__就是返回一个数据的内存地址
    print(l)
    print(str(l))
    print('%s'%l)
    print(obj)   的结果 是 obj.__str__()的结果
    str(obj)   的结果 也是 obj.__str__()的结果
    '%s'%obj   的结果 也是 obj.__str__()的结果
    复制代码
    复制代码
    class Teacher:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        # def __str__(self):
        #     return "Teacher's object is %s" %self.name
        def __repr__(self):
            return "repr %s" %self.name
    a = Teacher('alex',18)
    b = Teacher('wusir',18)
    
    print(a)
    print(repr(b))
    # repr(obj)的结果和obj.__repr__()是一样的
    # '%r'%(obj)的结果和obj.__repr__()是一样的
    复制代码

    总结:

      1.实际上上述三种结果都是__str__的返回值

      2.当然:如果我们不手动改写object中 的上下划线str或者repr,就会默认调用object类中的方法,默认返回的是 内存地址

    思考:why? repr(1)  与 repr('1'):的打印结果不同?

    因为:在整形中 定义的repr方法,与在str中定义的repr方法定义的函数方法的返回值不同。  即在class int 与 class str 中的 __repr__ 方法的返回值不同

    复制代码
    class Teacher:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __str__(self):
            return "Teacher's object %s"%self.name
        def __repr__(self):
            return 'repr function %s'%self.name
    a = Teacher('alex',80)
    b = Teacher('egon',80)
    print(a)
    print(b)

    复制代码

    PS:总结:

      1.到需要使用__str__的方法时,找不到__str__方法时,就会找__repr__方法。

      2.当需要使用__repr__的方法时,找不到__repr__的方法时,就会找父类的或object的__repr__方法,这是默认返回的时内存地址

      3.repr()方法是 str()方法的备胎。嘿嘿嘿(偷笑)

      3.实际上:len()和 repr() 方法的返回值都是依赖__len__和__repr__方法来返回值的

    三。__len__方法 与 __hash__方法

    # class A:
    # def __init__(self):pass
    # def __len__(self):pass
    # def len(obj):
    # obj.__len__()
    # a = A()
    # a.__len__()
    # len() # 为什么要归一化设计呢?
    # 更接近面向函数编程,简单且节省代码

    # len()  obj.__len__()  返回值是一致的
    # len() 的结果是依赖 obj.__len__()
    # hash() 的结果是依赖 obj.__hash__()

    # str() 的结果是依赖 obj.__str__()
    # print(obj) 的结果是依赖 obj.__str__()
    # %s 的结果是依赖 obj.__str__() # 语法糖
    #
    # repr() 的结果是依赖 obj.__repr__()
    # %r 的结果是依赖 obj.__repr__()
    # repr是str的备胎
    思考:如果str与repr 我只能实现一个,那选哪个?# __str__
    # __repr__   一定是选择repr


    什么是语法糖?语法糖的定义?
      
      答:语法糖就是可以让数据结构变得更加简单,就像吃了糖一样甜。这就是语法糖。

    四。__format__方法?
      
    复制代码
    class Format:
        def __init__(self,name,age,hobby):
            self.name = name
            self.age = age
            self.hobby = hobby
    
        def __format__(self,format_spec):
            return format_spec.format(obj = self)
    
    person = Format('alex',18,'女')
    format_spec = '{obj.name}-{obj.age}-{obj.hobby}'
    print(format(person,format_spec))
    复制代码

    五:__call__?

    复制代码
    class Teacher:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __call__(self):
            print(123)
    
    
    t = Teacher('wusir',18)
    t()
    复制代码

    靠?方法加(),什么鬼?  

    对象名()   相当于调用了类内置的__call__方法

    print(callable(类名)):是否可调用的

    如果一个对象是否可调用,取决于这个对象对应的类是否有__call__方法


    2.__eq__?
    class A:pass
    a = A()
    b = A()
    print(a == b)

    返回False
    因为连个对象的内存地址是不一样的,
    复制代码
    # class A:
    #     def __eq__(self, other):
    #         # if self.__dict__ == other.__dict__:
    #             return True
    # # __eq__()
    # a = A()
    # a.name = 'alex'
    # b = A()
    # b.name = 'egon'
    # print(a)
    # print(b)
    # print(a == b)
    
    # == 是由__eq__的返回值来决定的
    复制代码

    # == 是由__eq__的返回值来决定的

    3.__del__ 析构方法?

    在删除一个对象的时候做一些收尾工作。

    复制代码
    class A:
        def __init__(self):
            self.f = open('文件','w')
    
    a = A()
    print('aaa')

    复制代码

    把a对象删除不用了

    这是文件并没有关闭,文件没有关闭会占内存。

    应该在删除对象是进行一个析构方法,用操作系统将文件关闭在删除文件

    复制代码
    class A:
        def __init__(self):
            pass
            self.f = open('文件','w')
        def __del__(self):
            self.f.close()
            print('执行我了')
    
    a = A()
    del a
    print(a)
    print('aaa')
    复制代码

    4.__new__?

    __new__  构造方法

    实例化对象的时候

    创建对象的过程

    init  初始化

       设计模式 —— 单例模式

    复制代码
     单例模式 就是 一个类 只能有一个实例
    # class A:pass
    # a = A()
    # b = A()
    # print(a)
    # print(b)
    
    # class B:
    #     __instance = None
    #     def __new__(cls, *args, **kwargs):
    #         if cls.__instance is None:
    #             obj = object.__new__(cls)
    #             cls.__instance = obj
    #         return cls.__instance
    #     def __init__(self,name,age):
    #         self.name = name
    #         self.age = age
    #     def func(self):
    #         print(self.name)
    # a = B('alex',80)
    # b = B('egon',20)
    # print(a)
    # print(b)
    # print(a.name)
    # print(b.name)
    复制代码



    5.__item__系列
    复制代码
    # item
    # dic = {'k':'v'}
    # print(dic['k'])
    
    
    # class Foo:
    #     def __init__(self,name):
    #         self.name=name
    #
    #     def __getitem__(self,item):
    #         return  self.__dict__[item]
    #
    #     def __setitem__(self, key, value):
    #         self.__dict__[key]=value
    #
    #     def __delitem__(self, key):
    #         print('del obj[key]时,我执行')
    #         self.__dict__.pop(key)
    
    # f = Foo('alex')
    # # f.name = ...
    # print(f['name'])    # f.__getitem__('name')
    # f['age']  = 18      # 赋值
    # print(f.age)         # 自带的语法
    # print(f['age'])     # 修改
    # f['age']  = 80
    # print(f['age'])     # 通过实现__getitem__得到的
    # del f['age']
    # print(f.age)         # 删除
    
    # class Foo:
    #     def __init__(self,name):
    #         self.name=name
    #     def __delattr__(self, item):
    #         print('del obj.key时,我执行')
    #         self.__dict__.pop(item)
    # f = Foo('alex')
    # del f.name     #相当于执行了__delattr__
    # # delattr(f,'name')
    复制代码

    面试题:  

    # 写一个类 定义100个对象
    # 拥有三个属性 name age sex
    # 如果两个对象的name 和 sex完全相同
    # 我们就认为这是一个对象
    # 忽略age属性
    # 做这100个对象的去重工作
    class Person:
    def __init__(self,name,age,sex):
    self.name = name
    self.age = age
    self.sex = sex
    def __hash__(self):
    # hash算法本身就存在了 且直接在python中就能调用
    # 姓名相同 性别相同的对象的hash值应该相等才行
    # 姓名性别都是字符串
    return hash(self.name+self.sex)
    def __eq__(self, other):
    if self.name == other.name and self.sex == other.sex:
    return True
    # python2.7
    # 去重 set
    # hash方法
    # set([obj,obj]) unhashable
    # hash算法 一个值 进行一系列的计算得出一个数字在一次程序执行中总是不变
    #来让每一个不同的值计算出的数字都不相等
    obj_lst = []
    obj_lst.append(Person('alex',80,'male'))
    obj_lst.append(Person('alex',70,'male'))
    obj_lst.append(Person('alex',60,'male'))
    obj_lst.append(Person('boss_jin',50,'male'))
    obj_lst.append(Person('boss_jin',40,'male'))
    obj_lst.append(Person('boss_jin',30,'male'))
    obj_lst.append(Person('nezha',20,'male'))
    obj_lst.append(Person('nezha',10,'male'))
    obj_lst = set(obj_lst)
    for obj in obj_lst:print(obj.name)
    # set对一个对象序列的去重 依赖于这个对象的两个方法 hash eq


    # 可hash顺带着写的
    # eq来做判断

    # key hash 数字 --》 内存地址 --》 value
    # set hash 数字 --》 内存地址 --》 set中的元素
    # 'aaa' hash

    # java
    # set去重 一个容器中 有相同值的内容 __eq__
    # 当你这个容器中有10000个元素的时候 我判断第10000个元素
    # hash算法
    # 'abc'
    # 'bca'
    # set对一个对象序列的去重 如何判断这两个值是否相等
    # 值a进行hash --> 存值
    # 值b进行hash --> 判断值是否相等 -相等-> 说明是一样的
    #-不相等-> 在开辟一个空间 来存放b

     

  • 相关阅读:
    Linux 的启动流程(转)
    HDU 4686 Arc of Dream (矩阵快速幂)
    自己编写jQuery动态引入js文件插件 (jquery.import.dynamic.script)
    Oracle job procedure 存储过程定时任务
    Spring3 整合MyBatis3 配置多数据源 动态选择SqlSessionFactory
    Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
    Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
    软件设计之UML—UML的构成[上]
    软件设计之UML—UML中的六大关系
    ActiveMQ 即时通讯服务 浅析
  • 原文地址:https://www.cnblogs.com/zsdbk/p/9697463.html
Copyright © 2011-2022 走看看