1. 特殊方法__init__
基本结构
- 特殊方法不需要调用,系统会在特殊的时候自动调用该方法
- init()方法在创建对象时自动调用,用来对新创建的对象初始化属性
- 程序会首先执行类中的代码,再执行__init__()中的代码
class 类名([]):
公共属性
# 对象的初始化方法
def __init__(self,参数,...,参数n)
pass
# 其他的方法
def method1(self):
pass
def method2(self):
pass
...
- 代码示例:
# name是必须的,但是如果在函数中直接声明会写死,
# 但是在实例对象中声明又太费劲了
# 采用特殊方法解决这个问题
class Person:
print('测试谁先输出1')
# 特殊方法形如 __开头__
# 特殊方法不需要调用,系统会在特殊的时候自动调用该方法
# __init__方法在创建对象时自动调用
# 类中的代码先执行,再执行__init__中的代码
def __init__(self,name):
# print(self)
self.name = name
print('测试谁先输出2')
# name = '超人'
def speak(self):
print('大家好,我是%s'%self.name)
print('测试谁先输出3')
# 创建对象时要传入属性值,否则无法创建对象
# __init__函数会把传入的属性值赋值给self.name
# 所以函数就可以正常输出了
p1 = Person('鱼香肉丝')
p2 = Person('红烧肉')
p3 = Person('臭鳜鱼')
p4 = Person('满汉全席')
# p2 = Person()
#
# p1.name = '鱼香肉丝'
p1.speak()
# # 对象.属性名 = 属性值
# # 会覆盖class里的默认
# p2.name = '红烧肉'
p2.speak()
#
# p3 = Person()
# # 如果实例对象中没有定义,类对象也没有定义,则会报错,说'name'没有声明
# p3.name = '臭鳜鱼'
p3.speak()
p4.speak()
2. 封装
- 封装是面向对象的三大特性之一
- 封装就是隐藏不希望被外部访问的属性或方法
- 如果需要修改属性,则需要提供getter和setter方法使外部可以访问到属性并修改(比直接把属性名暴漏更加安全)
# # 定义一个车类
# '''
# 属性: name color
# 方法: run() speaker()
#
# '''
#
# class Car():
#
# def __init__(self,name,color):
# self.name = name
# self.color = color
#
# def run(self):
# print('%s开始启动'%self.name)
#
# def speaker(self):
# print('%s滴滴滴'%self.name)
#
# c = Car('宾利','紫色')
# # c.run()
# c.name = '奶牛'
# c.speaker()
#
# c.color = '黑不溜秋'
# print(c.color)
# 以上代码揭示了数据的不安全的问题
# 所以需要采用封装来保证数据的安全性
# 1.属性不能随意修改(权限控制)
# 2.属性不能改为任意值
class Dog:
# 第一步,不采用常用的属性名
def __init__(self,name,age):
self.hidden_name = name
self.hidden_age = age
def speak(self):
print('大家好,我是%s'%self.hidden_name)
print('我的狗龄是%s'%self.hidden_age)
# 一个getter方法,用来获取对象的name属性值
def get_name(self):
return print(self.hidden_name)
def get_age(self):
print('用户读取了属性')
return print(self.hidden_age)
# 一个setter方法,用来修改属性值
def set_name(self,name):
self.hidden_name = name
def set_age(self,age):
print('用户修改了属性')
# 加入判断
if age > 0:
self.hidden_age = age
else:
print('错误的输入')
d = Dog('哈士奇',13)
# d.name = '雪纳瑞'
# d.speak()
# # 所谓封装并不能完全隐藏属性名,而是使属性名不好猜而已
# # 防君子不防小人
# d.hidden_name = '萨摩耶'
# d.speak()
#
# # 获取属性值
# d.get_name()
#
# # 修改属性值
# d.set_name('柴犬')
# d.speak()
d.get_age()
d.set_age(8)
d.get_age()
-
如何使隐藏的属性进行隐藏,使之无法在外部直接通过 对象实例.属性的方式修改
-
可以为对象属性使用__的方式来封装,即在属性名之前增加__
-
隐藏属性只不过使Python自动为属性命名
-
__属性名 👉 _类名__属性名
-
代码示例2:
class Person:
def __init__(self,name):
# self.hidden_name = name
self.__name = name
def get_name(self):
return self.__name
def set_name(self,name):
self.__name = name
p = Person('兜兜')
p.set_name('乐乐')
p.hidden_name = '乱入'
print(p.get_name())
# AttributeError: 'Person' object has no attribute '__name'
# print(p.__name)
# 采用_类名__属性名的方式依然可以被访问到
print(p._Person__name)
- 注意:
- 不建议采用这种方式,代码可读性较差
- 封装是一种伪隐藏
- 建议写封装采取 _属性名 的形式
- 代码示例3:
class Person:
def __init__(self,name):
# self.hidden_name = name
self._name = name
def get_name(self):
return self._name
def set_name(self,name):
self._name = name
p = Person('兜兜')
p.set_name('乐乐')
p.name = '乱入'
print(p.get_name())
print(p._name)
3. property装饰器
- property:
- 属性
- 名词
- 属性, 性能, 财产
- @property 会将方法转换为同名的只读属性
- 代码示例:
class Person:
def __init__(self,name):
self._name = name
# 增加了装饰器
@property
# getter方法
def name(self):
print('getter方法执行了')
return self._name
@name.setter
def name(self,name):
print('setter方法执行了')
self._name = name
p = Person('兜兜')
# 加@property以后,函数就无法调用了
# TypeError: 'str' object is not callable
# print(p.name())
# @property把 对象实例.方法 的结果转化为 对象实例.属性 的方式返回
# 不加@property,则输出和函数没有关系
# 加了@property,则函数会运行
p.name = '乐乐'
print(p.name)
p.set_name = '金金'
print(p.name)
- 注意:
- getter()和setter()可以统一属性名,由装饰器名称区分属性的具体用途
- @property后的是getter()
- @方法名.setter后边的是setter()
- 作用是把方法转换为同名的属性