zoukankan      html  css  js  c++  java
  • Python面向对象高级编程

    1、__slots__

    Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性

    class Student(object):
        __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
    
    
    
    >>> s = Student() # 创建新的实例
    >>> s.name = 'Michael' # 绑定属性'name'
    
    >>> s.age = 25 # 绑定属性'age'
    
    >>> s.score = 99 # 绑定属性'score'
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'score'

    可以发现name age都可以赋值,score却提示错误,这是因为没有在__slots__中设置该属性名称

    注意:使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

    ------------------------------------------------------------------------------------------------------------------------------------

    2、property 方法转属性

    @property 把一个方法 伪装成一个属性 
    1.属性的值 是这个方法的返回值 
    2.这个方法不能有参数了 
    3.类不能调用,只能对象调用

    class Person:
        def __init__(self,name,height,weight):
            self.name = name
            self.height = height
            self.weight = weight
        @property
        def bmi(self):
            return self.weight / (self.height**2)
    
        @property
        def methdd(self):
            print("method")
    
    per = Person("safly",1.73,75)
    print(per.bmi)
    per.methdd
    #如下调用没有效果
    Person.methdd

    property-setter设置值

    class Goods:
        discount = 0.8
        def __init__(self,name,price):
            self.name = name
            self.price = price
    
        @property
        def getPrice(self):
            return self.price * Goods.discount
    
        @getPrice.setter
        def getPrice(self,newPrice):
            self.price= newPrice
    
    
    app = Goods("apple",10)
    print(app.getPrice)
    
    app.getPrice = 20
    
    print(app.getPrice)

    ------------------------------------------------------------------------------------------------------------------------------------

    3、Python多重继承,就是一个类可以继承多个类,获取到这些父类的属性和函数

    #哺乳类
    class Mammal(Animal):
        pass
    
    #可以跑得类
    class Runnable(object):
        def run(self):
            print('Running...')
    
    #即是哺乳类,又是可以跑得
    class Dog(Mammal, Runnable):
        pass
    
    如此Dog类就可以同时获得Mammal,Runnable类的所有功能

    不同于Java单继承 只能extends一个父类

    ------------------------------------------------------------------------------------------------------------------------------------

    4、一些定制类

    看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的。

    上面的__slots__ , 指定给实例添加哪些属性

    1、__str__ ,类似于java的toString()

    >>> class Student(object):
    ...     def __init__(self, name):
    ...         self.name = name
    ...     def __str__(self):
    ...         return 'Student object (name: %s)' % self.name
    ...
    >>> print(Student('Michael'))
    Student object (name: Michael)

    2、__repr__

    >>> s = Student('Michael')
    >>> s
    <__main__.Student object at 0x109afb310>
    因为直接显示变量调用的不是__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
    
    解决办法是再定义一个__repr__()。但是通常__str__()和__repr__()代码都是一样的,所以,有个偷懒的写法:
    
    class Student(object):
        def __init__(self, name):
            self.name = name
        def __str__(self):
            return 'Student object (name=%s)' % self.name
        __repr__ = __str__
     str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常 
     

    3、__getattr__

    调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性

    class Student(object):
    
        def __init__(self):
            self.name = 'Michael'
    
        def __getattr__(self, attr):
            if attr=='score':
                return 99
    
    
    -------------------------------------
    >>> s = Student()
    >>> s.name
    'Michael'
    >>> s.score
    99
    返回函数也是完全可以的:
    
    class Student(object):
        def __getattr__(self, attr):
            if attr=='age':
                return lambda: 25

    >>> s.age()
    25
     

    注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。

    4、__call__

    任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用。请看示例:
    
    class Student(object):
        def __init__(self, name):
            self.name = name
    
        def __call__(self):
            print('My name is %s.' % self.name)
    >>> s = Student('Michael')
    >>> s() # self参数不要传入
    My name is Michael.

    额外知识:

    那么,怎么判断一个变量是对象还是函数呢?其实,更多的时候,我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,比如函数和我们上面定义的带有__call__()的类实例:

    >>> callable(Student())
    True
    >>> callable(max)
    True
    >>> callable([1, 2, 3])
    False
    >>> callable(None)
    False
    >>> callable('str')
    False
    
    通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
  • 相关阅读:
    什么是内存碎片
    java堆内存模型
    java内存模型
    java垃圾回收过程
    找出给定的一个字符串中最长的不重复子串,不重复子串即一个子串中不出现两个相同的字符
    学习tomcat(八)
    学习Redis(二)
    学习k8s(四)
    学习docker(三)
    学习MySql(一)
  • 原文地址:https://www.cnblogs.com/xqxacm/p/9816872.html
Copyright © 2011-2022 走看看