类的属性和方法
- 类的属性可以分为:类属性,类对象属性。
- 类属性定义在对象方法之外,类对象属性定义在对象方法内。
- 类的方法可以分为:类方法,类对象方法,静态方法。
- 类属性和类方法可以由类直接调用,不必一定要初始化类对象。但是类方法不可以调用类对象属性。
- 私有属性,私有方法:在属性或方法前面添加"__"双下划线。
- 特殊方法: 以 _ _ 开头,_ _ 结尾的方法是特殊方法。可以直接调用,也可以通过一些内置函数或操作符来间接调用。常用的有:__init__(), __next__(), __len__(), __str__(), __getitem__().
- 类方法和静态方法需要在方法前面加上装饰器(“@…”)
class myclass:
# __init_()为初始化类实例的函数,自动调用。
def __init__(self, params):
pass
# my_function()为对象方法,必须包含"self"参数来表示该类,调用时不必传递。
def my_function(self):
pass
# 使用装饰器"@classmethod"说明这是一个类方法
@classmethod
def my_classmethod(cls): #注意此时"self"改为"cls"来表示该类。
pass
@staticmethod
def my_staticmethod(): #注意静态方法不需要用于表示该类的参数。
pass
Python私有成员
Python类的成员只有私有和公开两种。在定义类时,有的类成员不想被外部访问,可以将其私有化。
私有属性和私有方法
在定义属性或方法时,在属性名/方法名前添加双下划线 _ _,使其成为私有成分。
class Person:
def __init__(self, name, gender):
self.name = name
self.__gender = gender
def __showGender(self):
return "姓名为{0},性别为{1}".format(self.name, self.__gender)
P1 = Person("tom", "boy")
print(P1.name) # tom
# print(P1.__gender)
# P1.__showGender()
# 调用上述两个时,都会出现 AttributeError
如何实现的私有化
Python在实现私有化时,仅仅是在内部将私有成员的名称做了修改,即在前边添加了类名:
- 私有属性:_Person__gender(_类名__属性名)
- 私有方法:_Person__showGender() (_类名__方法名)
class Person:
def __init__(self, name, gender):
self.name = name
self.__gender = gender
def __showGender(self):
return "姓名为{0},性别为{1}".format(self.name, self.__gender)
P1 = Person("tom", "boy")
print(P1.name) # tom
print(P1._Person__gender)
P1._Person__showGender()
""" 输出结果
'tom'
'boy'
'姓名为tom,性别为boy'
"""
关于Python类成员命名的一个规则-受保护的成员
虽然Python中通过双下划线实现了成员私有化(严格意义上也未完全私有化,仅仅是修改了名称),但在实际应用中更推荐使用单下划线来定义受保护成员,以此来提醒调用者,这是受保护的成员,慎重调用。实际上使用单下划线来定义成员和普通成员一致,仅仅起到暗示作用。
如何实现属性的安全访问与赋值
如前文所述的私有、保护和普通成员,都不能保证在给属性直接赋值时参数是否有效。
- 使用函数来给参数赋值,在函数内检查参数有效性
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_name(self):
return self._name
def set_age(self, age):
if isinstance(age, int):
if (age < 0 | age > 18):
print("age must be between 1 and 18...")
else:
self._age = age
else:
raise ValueError("age must be 'int'...")
def get_age(self):
return self._age
p = Person('Tom', 10)
print(p.get_name())
p.set_age(12)
print(p.get_age())
- 使用 @property 装饰器来装饰类方法,使得类对象可以像调用属性一样调用方法,达到与上述代码相同的效果。
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
if isinstance(age, int):
self._age = age
else:
raise ValueError("age must be 'int'")
p = Person('tom', 12)
p.age = 23 # 实际调用 age.setter(23)
print(p.age) # 实际调用 age.getter()
@property 装饰器
property 是Python内置的一个类,创建并返回一个属性对象,这个对象有三个方法:getter(), setter(), deleter()。使用property可以将一个类方法变成属性调用。property 的部分源代码如下 :
class property(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
pass
def deleter(self, *args, **kwargs): # real signature unknown
""" Descriptor to obtain a copy of the property with a different deleter. """
pass
def getter(self, *args, **kwargs): # real signature unknown
""" Descriptor to obtain a copy of the property with a different getter. """
pass
def setter(self, *args, **kwargs): # real signature unknown
""" Descriptor to obtain a copy of the property with a different setter. """
pass
在实际使用中,我们有以下两种方式
- 方式1:直接调用 property,返回一个属性对象
class C(object):
def __init__(self, x):
self._x = x
def getx(self): return self._x
def setx(self, value): self._x = value
def delx(self): del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
temp = C(3)
temp.x = 5
print(temp.x)
- 方式2:使用 @property装饰器(相当于getter()) 和 @XXX.setter
class C(object):
@property
def x(self):
"I am the 'x' property."
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
类的继承
class father:
父类的实现
class child(father):
子类的实现
class father:
def __init__(self):
pass
def myfunction(self):
pass
class child(father):
def __init__(self):
#此处的super()作用:由于子类定义了__init__()函数,所以无法获取父类的属性,用这个函数则可以初始化子类的同时初始化父类,super()返回父类对象。
super().__init__()
pass
def myfunction(self):
pass