0
点赞
收藏
分享

微信扫一扫

Python小记——面向对象程序设计

​​菜鸟教程 面向对象​​

样例

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 参数传递一个对象名,用来明确指定访问哪个对象的数据成员。
  • 类变量:属于类本身,用于定义该类本身所包含的状态数据
  • 实例变量:属于该类的对象,用于定义对象所包含的状态数据
  • 方法:定义该类的对象的行为或功能的实现
>>> 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参数显式传递对象名
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编程时,一般不需要使用类方法或静态方法,程序完全可以使用函数来代替类方法或静态方法。但是在特殊的场景(比如工程模式),类方法和静态方法也是不错的选择。
  • 类的专有方法
    Python小记——面向对象程序设计_静态方法
    Python小记——面向对象程序设计_静态方法_02
    Python小记——面向对象程序设计_数据_03
    Python小记——面向对象程序设计_静态方法_04
    Python小记——面向对象程序设计_类方法_05
    Python小记——面向对象程序设计_类方法_06
    Python小记——面向对象程序设计_类方法_07

私有成员和公有成员

>>> 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'

运算符重载

#!/usr/bin/python3

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 = 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


举报

相关推荐

0 条评论