菜鸟教程 面向对象
样例
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)
>>> t
.test
= types
.MethodType
(test
, t
)
>>> t
.test
<bound method test of
<__main__
.Demo
object at
0x000000000074F9E8>>
>>> t
.test
(5)
方法
在类中定义的方法可以粗略分为四大类:公有方法、私有方法、静态方法和类方法。公有方法、私有方法都属于对象,私有方法的名字以两个下划线“__”开始,每个对象都有自己的公有方法和私有方法,在这两类方法中可以访问属于类和对象的成员; 公有方法通过对象名直接调用,私有方法不能通过对象名直接调用,只能在属于对象的方法中通过 self 调用或在外部通过 Python 支持的特殊方式来调用。 如果通过类名来调用属于对象的公有方法,需要显式为该方法的 self 参数传递一个对象名,用来明确指定访问哪个对象的数据成员。类变量:属于类本身,用于定义该类本身所包含的状态数据实例变量:属于该类的对象,用于定义对象所包含的状态数据方法:定义该类的对象的行为或功能的实现
>>> class Root:
"""这是一个类"""
__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
)
@
classmethod
def classShowTotal(cls
):
print(cls
.__total
)
@
staticmethod
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
.__value
: 5
Root
.__total
: 2
对象是类的实例。
对于类变量而言,它们就是属于在类命名空间内定义的变量,因此程序不能直接访问这些变量,程序必须使用类名/对象来调用类变量。通过对象访问类变量,本质上依然是通过类名在访问。
如果程序对一个对象的实例变量进行了修改,这种修改也不会影响到类变量和其他对象的实例变量。
创建对象的根本方法是构造方法,调用某个类的构造方法即可创建这个类的对象,Python无需使用new方法。
self 不是 python 关键字
在使用类调用实例方法的时候,Python不会自动为第一个参数绑定调用者。
u
= User
() User
.walk
(u
) <=> u
= User
() u
.walk
()
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中不存在严格意义上的私有成员。
In
[8]: class Fruit(object):
...: 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'
运算符重载
class 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
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