01. 面相对象-类的特殊方法
01.类的特殊方法
目前,对于person类来说 name属性是必须的,并且每一个对象当中的name属性基本上是不同的
在类中我们可以定义一些特殊的方法(魔术方法)
这些特殊方法它的格式例如 以__开头__结尾的方法
特殊的方法不需要我们自己调用
学习特殊方法
1.特殊方法什么时候调用
2.特殊方法有什么作用?
创建对象的流程
p1 = person
1.创建一个变量
2.在内存中创建一个新的对象
3.执行类中的代码块中的代码(只在类定义的时候执行一次)
4.init(self)方法执行
定义一个类的基本结构
‘’’
class 类名([父类])
公共属性
# 对象的初始化方法
def _init_(self):
....
def method1(self.......):
def method2(self.......):
....
‘’’
class person():
# print('person代码块中的代码')
# name = '葫芦娃'
# 特殊的方法不需要我们自己调用,不要去尝试调用特殊方法
# 特殊的方法会在特殊的时候自己调用(一般就是解析器调用)
def __init__(self,name):
# print('init方法执行了')
# print(self)
# 通过self向新创建的对象中初始化属性
# self.name = '葫芦娃'
self.name = name
def speak(self):
print('大家好,我是%s'%self.name)
p1 = person('葫芦娃')
p2 = person('钢铁侠')
p3 = person('蜘蛛侠')
p4 = person('战狼')
print(p1.name)
print(p2.name)
print(p3.name)
print(p4.name)
p1.speak()
p2.speak()
p3.speak()
p4.speak()
# p1.__init__()
# # 手动添加对象的name属性
# p1.name = '葫芦娃'
# p1.speak()
# p2 = person()
#
# p2.name = '钢铁侠'
# p2.speak()
#
#
# p3 = person()
#
# p3.name = '蜘蛛侠'
# p3.speak()
02. - 面向对象 - 练习
‘’’
属性:
name
color
方法:
run()
laba()
‘’’
‘’’
关于错误:object() takes no parameters
先说结论:
如果你出现了这个报错,请检查你的__init__函数名或者其定义有没有写错。
注意:下划线左右是两个;中间的英文字母是四位,请一一对应。
--------------------------------------如果你有兴趣可以看看下面的分析过程------------------------------------
一、现象
先贴上自己出错的代码:
class Perceptron(object):
def int(self, eta=0.01, n_iter=10):
self.eta = eta
self.n_iter = n_iter
pass
pass
ppn=Perceptron(eta=0.1,n_iter=10)
报错如下:
Traceback (most recent call last):
File “D:/PyCharm/Neutron/Perceptron.py”, line 13, in
ppn=Perceptron(eta=0.1,n_iter=10)
TypeError: object() takes no parameters
为什么会这样呢?
二、分析
”object() takes no parameters”这句话的意思是:object()不需要传进参数。
笔者瞬间就感到纳闷了,为什么不需要传入参数?我不是定义了初始化函数吗?这初始化函数里面有俩参数啊,为什么不能传递呢?(这位朋友,你戏真多)
最可能的解释是:
在实例化一个对象的时候,使用 类名+(参数)并没有成功调用到这个初始化参数,编译器默认调用类名+( ) ,这是一个无参的初始化函数,自然就不需要传进参数了。
如果尝试调用自己定义的初始化函数的方法没有错的话,那么之所以不能成功调用初始化函数,错误就在于初始化函数本身!
回去检查一下我写的这个初始化函数,猛地发现我把__init__写成了__int__,难怪啊!
改成正确的函数名以后,就可以成功调用,不会报错了~
‘’’
class car():
# __init__函数 下划线左右是两个,中间的英文字母是四位:init
def __init__(self,name,color):
self.name = name
self.color = color
def run(self):
print('汽车开始跑了~~~~~')
def laba(self):
print('%s 滴滴滴滴'%self.name)
# 目前,我们是可以通过 对象.属性 的方式来修改属性的值,这种方式就可以导致对象中的属性可以随意修改
c = car('大奔','白色')
c.name = '法拉利'
c.color = '黑不溜秋'
print(c.name,c.color)
c.run()
c.laba()
我们想要增加数据的安全性,那么我们要做到两点
1.属性不能随意修改
2.属性不能改为任意值
03. - 面向对象 - 封装一
封装是面向对象的三大特征之一
封装是指隐藏对象中一些不希望被外部访问到的属性和方法
如何隐藏对象啊行中的属性
将对象的属性名修改成外部不知道的名字
如何获取(修改)对象当中的属性
需要提供一个getter和setter方法使外部可以访问到属性
‘’’
使用封装确实增加了类定义的复杂程度,但是它也确保了我们数据的安全性
1.隐藏了属性名,使用者无法随意的修改对象的属性
2.增加了getter和setter方法之后,很好的控制了属性是否是只读的
如果你希望属性是只读的,则可以直接去调用getter方法
如果希望属性不能被外部访问,则可以去调用getter方法
3.使用setter方法设置属性,可以增加数据的验证,确保数据的正确性
4.使用getter方法获取属性,使用setter方法设置属性
我们可以在读取属性和修改属性的时候做一些其他的操作
5.setter 和 getter方法也可以表示一些计算的属性
‘’’
hidden在这里是隐藏的意思
class dog():
def __init__(self,name,age):
self.hidden_name = name
self.hidden_age = age
def speak(self):
print('大家好,我是%s'%self.hidden_name)
# get_name(self) 获取对象中指定的属性(get_属性名)
def get_name(self):
# get_name(self)用来获取对象的name属性
print('get_name执行了')
return self.hidden_name
# set_name(self, ): 用来设置对象中指定的属性值(set_属性名)
def set_name(self,name):
print('set_name执行了')
self.hidden_name = name
def get_age(self):
return self.hidden_age
def set_age(self,age):
if age > 0:
self.hidden_age = age
d = dog('二哈',5)
# d.hidden_name = '德国牧羊犬' # 这个不是封装,而是暴力修改
# print(d.get_name())
# 调用setter来修改name的属性值
d.set_name('德牧')
d.set_age(8)
# print(d.get_name())
print(d.get_age())
# d.speak()
>>>
set_name执行了
8
04.- 面向对象 - 封装二
练习:计算长方形的面积
class Rect():
def __init__(self,width,height):
self.hidden_width = width
self.hidden_height = height
def get_width(self):
return self.hidden_width
def get_height(self):
return self.hidden_height
def set_width(self,width):
self.hidden_width = width
def set_height(self,height):
self.hidden_height = height
def get_area(self):
return self.hidden_width * self.hidden_height
r = Rect(2,3)
r.set_width(5)
r.set_height(10)
print(r.get_area())
>>>
>50
如果我希望封装的更加彻底,外部访问不到
可以为对象的属性使用双下划线 __xxx
__双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象来访问
__name --> _person__name 实际上是将名字改为 _类名__属性名
一般我们会将一些私有属性(不希望被外部访问的属性) 以_xx 开头(一个下划线就可以了)
class person():
def __init__(self,name):
# self.hidden_name = name
self._name = name
def get_name(self):
# return self.hidden_name
return self._name
def set_name(self,name):
# self.hidden_name = name
self._name = name
p = person('葫芦娃')
# p.set_name('钢铁侠')
# p.hidden _name = '蜘蛛侠'
# print(p._person__name)
# p._person__name = '蜘蛛侠'
# p.__name = '蜘蛛侠'
# print(p.get_name())
print(p._name)
self._name 这样写的好处是什么?
1.一个下划线要比两个下划线要容易书写
2.外部依然可以读取
3.我以这种方式来写就是告诉你不希望你来修改
05. - 面向对象 - property()装饰器
property(), 是用来将一个get()方法,转换为一个属性
class person():
def __init__(self,name):
self._name = name
@property
def name(self):
print('get方法执行了')
return self._name
# 设置setter方法的装饰器 @属性名.setter
@name.setter
def name(self,name):
print('set方法执行了')
self._name = name
p = person('葫芦娃')
# print(p.name())
p.name = '钢铁侠'
print(p.name)
>>>
set方法执行了
get方法执行了
钢铁侠