1 特殊方法
参考资料:
Python 特殊方法一览 来源:优快云
Python的特殊方法 来源:优快云
特殊方法: 特殊方法也称魔法方法,形如__xxx__() 这种形式(如:__ str__)可以在类中定义,他们无需程序员调用,在特定的时候会自动调用
常见特殊方法:(以下图片来自上述博文:Python 特殊方法一览)
2 构造函数和构析函数
参考资料:
Python面向对象编程-封装
- 构造函数: python中的构造函数是__init__(),用于初始化类对象的初始化,__ init__()方法是可选的,如果不提供,python会给出一个默认的__init__()方法。
- 构析函数: python中的析构函数是__del__(),用于释放对象占用的资源。析构函数也是可选的,如果不提供,则python会提供默认的析构函数。如果要显示调用析构函数,可以使用del关键字。
3 封装
参考资料:
第十二讲—面向对象二 来源:优快云
Python面向对象编程-封装 来源:优快云 (强烈推荐)
- 封装: 封装是面向对象的三大特性之一,是指隐藏对象中一些不希望被外部访问到的属性或方法
- 封装 封装是指隐藏对象中一些不希望被外部访问到的属性或者方法,达到增强数据安全,使得属性不能随意更改
- 优点:
- 隐藏了属性名,调用类时就无法随意修改对象中的属性
- 增加了getter()和setter()方法,很好的控制了属性是否是只读类型
- 如果希望属性只读,则可以直接去掉setter方法
- 如果希望属性不能被外部访问,则可以直接去掉getter方法
- 使用getter方法和setter方法获取和设置属性的时候,可以在读取属性和修改属性的时候做一些其他的操作
- 无法随意修改对象属性的方法: 隐藏属性名,即在对象的属性前使用双下划线(形如:__ xxx),双下划线开头的属性就是对象的隐藏属性,只能在类的内部访问,无法通过对象访问
- 访问隐藏属性方法:_ 类名__ 属性名
一般情况下,通过_ 类名__ 属性名的方法依然可以在外部访问属性,所以此方式一般不用,只将一些私有属性以_ 开头,且没有特殊情况,尽量不修改私有属性 - 类的成员变量和对象的成员变量: 类的成员变量定义在类中,和类的成员函数在同一缩进等级。而对象的成员变量定义在__init__(self)成员函数中,和__init__(self)函数下的变量和语句在同一等级。通俗地讲,类的成员变量属于类,共类的所有对象和类本身所共有,也就是说所有的类的对象和类只有一份这样的变量。而对象的成员变量属于类的对象本身,每个对象都有一份,而且各个对象之间互不影响。
- 属性分类:
- 类属性: 类属性是指在类中直接定义的属性,分为私有类属性(形如:__ xxx)和普通类属性,类属性只能通过类对象来修改,无法通过实例对象修改
- 实例属性(对象属性): 实例属性是指通过实例对象添加的属性,只能通过对象来访问或者修改,类对象无法访问以及修改
- 方法分类:
- 实例方法: 在类中定义,以self为第一个参数的方法都是实例方法,可以通过实例和类调用,在通过实例调用时会将调用对象以self自动传入,当通过类调用时,不会自动传递self,我们必须手动传入self
- 类方法: 指在类中用@classmethod 修饰的方法,类方法第一个参数是cls,也会自动被传递,cls就是当前的类对象,类方法可以通过实例调用,也可以通过类调用
- 静态方法: 指在类中用@staticmethod修饰的方法,它不需要指定任何的默认方法,可以通过类和实例调用(静态方法基本是一个和当前类无关的方法,只是一个保存在当前类的函数,一般都是一些工具方法,和当前类无关)
- 公有成员变量和私有成员变量: python中用成员变量的名字来区分是共有成员变量或者是私有成员变量。python中,以两个下划线‘__’开头的变量都是私有成员变量,而其余的变量都属于公有成员变量。其中,私有的成员变量只能在类的内部访问,而共有的公有的成员变量可以在类的外部进行访问。
注:此代码为复制代码,强烈推荐原文,地址为:Python面向对象编程-封装
#实例1
class Person():
# 人口数和土地面积属于人类共享的信息,设置为类公有变量
population = 0
earth = 10000
# 诺亚方舟能再多少人,自然不应该让每个人都知道,设置为类私有变量
__noahCapacity = 10
def __init__(self, name, age, salary):
# 名字就是用来让大家知道的,每个人不一样,所以这里设置为对象的公有变量
self.name = name
# 年龄也类似,设置为对象的公有变量
self.age = age
# 薪水当然属于每个人都很敏感的啦,设置为对象的私有变量
self.__salary = salary
def __privateFun(self):
print("这是私有成员函数的输出")
# 在类的内部访问对象的公有和私有变量
def printInstance(self):
print("*" * 50, "公有成员函数被调用", "*" * 50)
print("在类内部可以通过self访问对象的公有和私有变量:")
print("name: %s age: %d salary:%d" % (self.name, self.age, self.__salary))
print("通过类内部的成员函数,在类的内部调用私有成员函数:")
self.__privateFun()
print("*" * 120)
# 在类的内部访问类的公有变量和私有变量
def printClass(self):
print("-" * 50, "公有成员函数被调用", "-" * 50)
print("在类内部可以通过self访问类的公有和私有变量:")
print("population: %d earth: %d NoahCapacity: %d" % (self.population, self.earth, self.__noahCapacity))
print("在类内部也可以通过类名访问类的公有和私有变量:")
print("population: %d earth: %d NoahCapacity: %d" % (Person.population, Person.earth, Person.__noahCapacity))
print("-" * 120)
if __name__ == "__main__":
tom = Person("Tom", 24, 9000)
print("在类外部访问属性操作", "|" * 100)
print("在类外部可以通过对象名访问类的公有变量:")
print("population: %d earth: %d" % (tom.population, tom.earth))
print("在类外部也可以通过对象名用特殊方法访问类的私有变量(仅用于调试):")
print("NoahCapacity: %d" % tom._Person__noahCapacity)
print("在类外部可以通过对象名访问对象的公有变量:")
print("name: %s age: %d" % (tom.name, tom.age))
print("在类外部也可以通过类名访问类的公有变量:")
print("population: %d earth: %d" % (Person.population, Person.earth))
print("|" * 120)
print("")
print("在类的外部调用类的成员函数", "|" * 100)
print("在类外通过对象名调用类的公有成员函数")
tom.printInstance()
tom.printClass()
print("|" * 120)
运行结果:
以上代码结论总结为:
4 property装饰器
- property装饰器作用: 使用@property装饰器创建只读属性,@property也可以将方法伪装成同名称的只读属性,这样便可以与所定义的属性配合使用,防止属性被修改
示例原文链接:(python)面向对象三大特性之(封装)
#面向对象 @property示例一
class Pepple:
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height
@property
def bmi(self):
return self.weight/(self.height*self.height)
monicx=Pepple('monicx',63,1.78)
zzzz=Pepple('ZZZZ',55,1.58)
#首先需要明确,bmi是算出的,不是一个固定的值,我们必须编写一个功能,每次调用都会立即计算一个值
# monicx.bmi=monicx.weight/(monicx.height*monicx.height)
# print(monicx.bmi)
# print(zzzz.bmi())
# print(monicx.bmi())
#bmi不是一个功能虽一个特征,使用函数不太好,最好是一个变量属性为好。
#于是我们需要为bmi这个函数添加装饰器(property),将其伪装成一个数据属性
print(zzzz.bmi)
#此时调用zzzz.bim本质就触发函数bmi执行,从而拿到其返回值。
print(monicx.bmi)
'''
运行结果:
22.031725684986377
19.883853048857468
'''
#----------------------------------------------------------------
#面向对象 @property示例二
class People:
def __init__(self, name):
self.__name = name
@property
def name(self): # obj.name
print('访问用户名。。。')
return self.__name
# 修改用户名
@name.setter # obj.name='monicx'
def name(self, x):
if type(x) is not str:
raise TypeError('名字必须是str类型')
self.__name = x
# 删除用户名
@name.deleter
def name(self):
print('可以在这里加上判断用户的管理权限。是否让其删除')
del self.__name
obj = People('egon')
print(obj.name)
del obj.name
# obj.name
'''
运行结果:
访问用户名。。。
egon
可以在这里加上判断用户的管理权限。是否让其删除
'''