天天看点

python面向对象高级编程_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 "", line 1, in

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()函数,我们就可以判断一个对象是否是“可调用”对象。