菜鸟教程 面向对象 样例 In [ 1 ]: class A ( object ): ... : def __init__ ( self , v ): ... : self . value = v ... : def show ( self ): ... : print ( self . value ) ... : In [ 2 ]: a = A ( 3 ) In [ 3 ]: a . show () 3 在
菜鸟教程 面向对象
样例
In [1]: class A(object):...: def __init__(self, v):
...: self.value = v
...: def show(self):
...: print(self.value)
...:
In [2]: a = A(3)
In [3]: a.show()
3
在Python中比较特殊的是,可以动态地为类和对象增加成员
class Car:price = 100000 #定义类属性
def __init__(self, c):
self.color = c #定义实例属性
car1 = Car("Red") #实例化对象
car2 = Car("Blue")
print(car1.color) #查看实例属性
print(Car.price) #查看类属性的值
Car.price = 110000 #修改类属性
Car.name = 'QQ' #动态增加类属性
car1.color = "Yellow" #修改实例属性
print(car2.color, Car.price, Car.name)
print(car1.color, Car.price, Car.name)
import types
def setSpeed(self, s):
self.speed = s
car1.setSpeed = types.MethodType(setSpeed, car1) #动态增加成员方法
car1.setSpeed(50) #调用成员方法
print(car1.speed)>>> import types
>>> class Person(object):
def __init__(self, name):
assert isinstance(name, str), 'name must be string'
self.name = name
>>> def sing(self):
print(self.name+' can sing.')
>>> def walk(self):
print(self.name+' can walk.')
>>> def eat(self):
print(self.name+' can eat.')>>> zhang = Person('zhang')
>>> zhang.sing() #用户不具有该行为
AttributeError: 'Person' object has no attribute 'sing'
>>> zhang.sing = types.MethodType(sing, zhang)
#动态增加一个新行为
>>> zhang.sing()
zhang can sing.
>>> zhang.walk()
AttributeError: 'Person' object has no attribute 'walk'
>>> zhang.walk = types.MethodType(walk, zhang)
>>> zhang.walk()
zhang can walk.
>>> del zhang.walk #删除用户行为
>>> zhang.walk()
AttributeError: 'Person' object has no attribute 'walk'
函数和方法是有区别的
>>> class Demo:pass
>>> t = Demo()
>>> def test(self, v):
self.value = v
>>> t.test = test
>>> t.test #普通函数
<function test at 0x00000000034B7EA0>
>>> t.test(t, 3) #必须为self参数传值>>> t.test = types.MethodType(test, t)
>>> t.test #绑定的方法
<bound method test of <__main__.Demo object at 0x000000000074F9E8>>
>>> t.test(5) #不需要为self参数传值
方法
- 在类中定义的方法可以粗略分为四大类:公有方法、私有方法、静态方法和类方法。
- 公有方法、私有方法都属于对象,私有方法的名字以两个下划线“__”开始,每个对象都有自己的公有方法和私有方法,在这两类方法中可以访问属于类和对象的成员;
公有方法通过对象名直接调用,私有方法不能通过对象名直接调用,只能在属于对象的方法中通过 self 调用或在外部通过 Python 支持的特殊方式来调用。
如果通过类名来调用属于对象的公有方法,需要显式为该方法的 self 参数传递一个对象名,用来明确指定访问哪个对象的数据成员。 - 类变量:属于类本身,用于定义该类本身所包含的状态数据
- 实例变量:属于该类的对象,用于定义对象所包含的状态数据
- 方法:定义该类的对象的行为或功能的实现
"""这是一个类""" #类定义说明文档
__total = 0 #类变量在整个实例化的对象中是公用的。类变量通常不作为实例变量使用
def __init__(self, v): #构造方法
value = 0 #局部变量
self.__value = v #实例变量
Root.__total += 1 #通过类来访问类变量
def show(self): #普通实例方法
print('self.__value:', self.__value)
print('Root.__total:', Root.__total)
#修饰器,声明类方法
def classShowTotal(cls): #类方法
print(cls.__total)
#修饰器,声明静态方法
def staticShowTotal(): #静态方法
print(Root.__total)
>>> r = Root(3)
>>> r.classShowTotal() #通过对象来调用类方法
1
>>> r.staticShowTotal() #通过对象来调用静态方法
1
>>> r.show()
self.__value: 3
Root.__total: 1
>>> rr = Root(5)
>>> Root.classShowTotal() #通过类名调用类方法
2
>>> Root.staticShowTotal() #通过类名调用静态方法
2
>>> Root.show() #试图通过类名直接调用实例方法,失败
TypeError: unbound method show() must be called with Root instance as first argument (got nothing instead)
>>> Root.show(r) #但是可以通过这种方法来调用方法并访问实例成员
self.__value: 3
Root.__total: 2
>>> Root.show(rr) #通过类名调用实例方法时为self参数显式传递对象名
self.__value: 5
Root.__total: 2
- 对象是类的实例。
- 对于类变量而言,它们就是属于在类命名空间内定义的变量,因此程序不能直接访问这些变量,程序必须使用类名/对象来调用类变量。通过对象访问类变量,本质上依然是通过类名在访问。
- 如果程序对一个对象的实例变量进行了修改,这种修改也不会影响到类变量和其他对象的实例变量。
- 创建对象的根本方法是构造方法,调用某个类的构造方法即可创建这个类的对象,Python无需使用new方法。
- self 不是 python 关键字
- 在使用类调用实例方法的时候,Python不会自动为第一个参数绑定调用者。
- Python只要求手动为第一个参数绑定参数值,并不要求必须绑定User对象,User.walk(“asd”)也可。
- 当Python对象的一个方法调用另一个方法时,不可以省略self。
- 类方法的第一个参数(通常为cls)会自动绑定到类本身,但是对于静态方法则不会自动绑定。
- 静态方法和类方法都可以通过类名和对象名调用,但不能直接访问属于对象的成员,只能访问属于类的成员。
- 静态方法可以没有参数。
- 一般将cls作为类方法的第一个参数名称,但也可以使用其他的名字作为参数,并且在调用类方法时不需要为该参数传递值。
- 在使用Python编程时,一般不需要使用类方法或静态方法,程序完全可以使用函数来代替类方法或静态方法。但是在特殊的场景(比如工程模式),类方法和静态方法也是不错的选择。
- 类的专有方法
私有成员和公有成员
>>> class A:def __init__(self, value1 = 0, value2 = 0):
self._value1 = value1
self.__value2 = value2
def setValue(self, value1, value2):
self._value1 = value1
self.__value2 = value2
def show(self):
print(self._value1)
print(self.__value2)
>>> a = A()
>>> a._value1
0
>>> a._A__value2 #在外部访问对象的私有数据成员
0
- 在Python中,以下划线开头的变量名和方法名有特殊的含义,尤其是在类的定义中。用下划线作为变量名和方法名前缀和后缀来表示类的特殊成员:
_xxx:受保护成员,不能用’from module import *'导入;
__xxx__:系统定义的特殊成员;
__xxx:私有成员,只有类对象自己能访问,子类对象不能直接访问到这个成员,但在对象外部可以通过“对象名._类名__xxx”这样的特殊方式来访问。
注意:Python中不存在严格意义上的私有成员。
...: value = 1
...: def __init__(self):
...: self.__color = 'Red'
...: self._num = 0.1
...: self.price = 1
...: def show(self):
...: print("value:{},color:{},num:{},price:{}".f
...: ormat(self.value, self.__color, self._num, self.pri
...: ce))
...:
In [9]: f = Fruit()
In [10]: f.show()
value:1,color:Red,num:0.1,price:1
In [11]: f.value
Out[11]: 1
In [12]: f.__color
------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-12-8047530fa8c8> in <module>
----> 1 f.__color
AttributeError: 'Fruit' object has no attribute '__color'
In [13]: f._num
Out[13]: 0.1
In [14]: f.price
Out[14]: 1>>> class Fruit:
def __init__(self):
self.__color = 'Red'
self.price = 1
>>> apple = Fruit()
>>> apple.price #显示对象公开数据成员的值
1
>>> apple.price = 2 #修改对象公开数据成员的值
>>> apple.price
2
>>> print(apple.price, apple._Fruit__color) #显示对象私有数据成员的值
2 Red
>>> apple._Fruit__color = "Blue" #修改对象私有数据成员的值
>>> print(apple.price, apple._Fruit__color)
2 Blue
>>> print(apple.__color) #不能直接访问对象的私有数据成员,出错
AttributeError: Fruit instance has no attribute '__color'
运算符重载
#!/usr/bin/python3class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)In [18]: v1 + v2
Out[18]: <__main__.Vector at 0x1f935fa5cf8>Vector(7,8)
在程序中,可以使用一个下划线来表示不关心该变量的值。
>>> for _ in range(5):print(3, end=' ')
3 3 3 3 3
>>> a, _ = divmod(60, 18) #只关心整商,不关心余数,等价于a = 60//18
>>> a
3
属性
将属性设置为可读、可修改、可删除。
class Test:def __init__(self, value):
self.__value = value
def __get(self):
return self.__value
def __set(self, v):
self.__value = v
def __del(self):
del self.__value
value = property(__get, __set, __del)
def show(self):
print(self.__value)
>>> t = Test(3)
>>> t.show()
3
>>> t.value
3
>>> t.value = 5
>>> t.show()
5
>>> t.value
5
>>> del t.value #删除属性
>>> t.value #对应的私有数据成员已删除
AttributeError: 'Test' object has no attribute '_Test__value'
>>> t.show()
AttributeError: 'Test' object has no attribute '_Test__value'
>>> t.value =1 #为对象动态增加属性和对应的私有数据成员
>>> t.show()
1
>>> t.value
1