第十五章:封装

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方法执行了
钢铁侠
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值