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

注意,只有在没有找到属性的情况下,才调用__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()函数,我们就可以判断一个对象是否是“可调用”对象。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

BZOJ4241: 历史研究(回滚莫队)

如果询问的两个端点在同一个块中,直接暴力计算,时间复杂度$O(\sqrt{n})$

13010
来自专栏技术小站

c++(二)

算数运算符:+,-,*,/,%,++,--  进行算数运算时,如果存在溢出,则把溢出的部分拿掉(浮点型的难以预测),如 int i=0xffffffff,j;j...

12210
来自专栏IT可乐

Java数据结构和算法(九)——高级排序

  春晚好看吗?不存在的!!!   在Java数据结构和算法(三)——冒泡、选择、插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(...

42760
来自专栏Phoenix的Android之旅

你不知道的HashMap

面试中经常会问到常用数据结构,比如HashMap。 相信你平时几乎每天都会用到HashMap,但是你知道它是的实现原理是怎样的吗? 这里先提几个问题:HashM...

11030
来自专栏武培轩的专栏

剑指Offer-包含min函数的栈

package Stack; import java.util.Stack; /** * 包含min函数的栈 * 定义栈的数据结构,请在该类型中实现一个...

28360
来自专栏用户2442861的专栏

Python之逻辑运算和缩进和选择if

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

9510
来自专栏菩提树下的杨过

python:函数的高级特性

24030
来自专栏我是攻城师

在Scala里面如何使用正则处理数据

34950
来自专栏用户2442861的专栏

STL list源码分析以及实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/d...

13730
来自专栏codingforever

经典算法巡礼(一) -- 排序之冒泡排序

事实上,她重复地遍历需要排序的元素,一次比较相邻的两个元素,如果不满足预先定义的比较条件,则交换;否则继续下一组元素比较,直至遍历完成需要排序的所有元素。当然,...

4820

扫码关注云+社区

领取腾讯云代金券