一、数据成员(属性)
数据成员可以大致分为两类:属于对象的数据成员和属于类的数据成员。
- 属于对象的数据成员一般在构造方法__init__()中定义,当然也可以在其他成员方法中定义,在定义和在实例方法中访问数据成员时以self作为前缀,同一个类的不同对象(实例)的数据成员之间互不影响;
- 属于类的数据成员是该类所有对象共享的,不属于任何一个对象,在定义类时这类数据成员一般不在任何一个成员方法的定义中。
二、成员方法
Python类的成员方法大致可以分为公有方法、私有方法、静态方法、类方法这几种类型。
-
公有方法、私有方法一般是指属于对象的实例方法,私有方法的名字以两个下划线"__"开始,而抽象方法一般定义在抽象类中并且要求派生类必须重新实现。每个对象都有自己的公有方法和私有方法,在这两类方法中都可以访问属于类和对象的成员。
-
公有方法通过对象名直接调用“对象名.公有方法(<实参>)”,私有方法不能通过对象名直接调用,只能在其他实例方法中通过前缀self进行调用或在外部通过特殊的形式来调用。
-
所有实例方法都必须至少有一个名为self的参数,并且必须是方法的第一个形参(如果有多个形参的话),self参数代表当前对象。
-
在实例方法中访问实例成员时需要以self为前缀,但在外部通过对象名调用对象方法时并不需要传递这个参数。
-
如果在外部通过类名调用属于对象的公有方法,需要显式为该方法的self参数传递一个对象名,用来明确指定访问哪个对象的成员。
-
静态方法和类方法都可以通过类名和对象名调用,但不能直接访问属于对象的成员,只能访问属于类的成员。
-
静态方法和类方法不属于任何实例,不会绑定到任何实例,当然也不依赖于任何实例的状态,与实例方法相比能够减少很多开销。
-
类方法一般以简写cls作为类方法的第一个参数表示该类自身,在调用类方法时不需要为该参数传递值,静态方法则可以不接收任何参数。
>>> class Root:
__total = 0
def __init__(self, v): #构造方法
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
三、方法属性
- 使用@porperty装饰器装饰方法,程序中可以把函数“当作”属性访问,从而提供更加友好的访问方式。
只读属性:
>>> class Test:
def __init__(self, value):
self.__value = value
@property
def value(self): #只读,无法修改和删除
return self.__value
>>> t = Test(3)
>>> t.value
3
>>> t.value = 5 #只读属性不允许修改值
AttributeError: can't set attribute
>>> t.v=5 #动态增加新成员
>>> t.v
5
>>> del t.v #动态删除成员
>>> del t.value #试图删除对象属性,失败
AttributeError: can't delete attribute
>>> t.value
3
可读、可写属性:
>>> class Test:
def __init__(self, value):
self.__value = value
def __get(self):
return self.__value
def __set(self, v):
self.__value = v
value = property(__get, __set)
def show(self):
print(self.__value)
>>> t = Test(3)
>>> t.value #允许读取属性值
3
>>> t.value = 5 #允许修改属性值
>>> t.value
5
>>> t.show() #属性对应的私有变量也得到了相应的修改
5
>>> del t.value #试图删除属性,失败
AttributeError: can't delete attribute
可读、可修改、可删除的属性:
>>> 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
class asd:
def __init__(self):
self.a = [100,200,300]
def func(p):
p.a=10
n=asd()
print(n.a)
func(n)
print(n.a)
#换成类方法也一样
class asd:
def __init__(self):
self.a = [100,200,300]
class YOLOv3:
def __init__(self):
self.num_classes = [1,2,3]
def func(self,p):
self.num_classes = 100
p.a=10
m=YOLOv3()
n=asd()
print(m.num_classes)
m.func(n)
print(m.num_classes)
class asd:
def __init__(self):
self.a = [100,200,300]
def func(p):
p=10
p.append(1)
return p
#或者不返回
n=asd()
print(n.a)
m=func(n)
print(n.a)
print(m)
m.append(2)
print(n.a)
print(m)
class asd:
def __init__(self):
self.a = [100,200,300]
def func(p):
#p=10
p.append(1)
n=asd()
print(n.a)
func(n)
print(n.a)
class YOLOv3:
def __init__(self):
self.num_classes = 12
def func(p):
p=p+1
m=YOLOv3()
print(m.num_classes)
m.func()
print(m.num_classes)
一定要充分理解python设计思想,同时遵守一些设计准则,保证可读性,理解计算机系统中内存与运算,达到python之禅的境界。
参考:
https://blog.csdn.net/zag666/article/details/105209782
https://www.cnblogs.com/xianranzhang/p/10683124.html
https://www.cnblogs.com/chxb/p/11220366.html