python练习生|面向对象——慢慢构建(类的初始化(__init__())、封装、@property装饰器)

一.类的初始化(init())

1.特殊方法

  • 我们在类中可以定义⼀些特殊⽅法,也称为魔术⽅法。
  • 这些特殊⽅法都是如__xxx__()这种形式。
  • 相对于普通方法需要调⽤,特殊方法会在特定时候⾃动调⽤。

2.特殊方法__init__()的用法

  • init()对新创建的对象进行初始化操作,是初始化魔术方法。
  • 下面我们举例介绍:
#__init__()方法
class Person():
    def __init__(self):
        print("奥利给!!!")

n1 = Person()
n1.__init__()

__init__()方法的使用01
__init__()方法的使用02

  • 由上面两幅图对比图可知,魔术方法__init__()进了自动调用。
    对照
  • 上面这幅图是上一篇博客在进行类对象中 方法的构建 以及 self 参数使用时举的例子,从图我们可以看出实例对象 n1和n2都有属性的赋值,但是实例对象n3则是调用了类对象中的参数值。如果我们对类对象中的参数进行“掩饰”,则会显示实例对象n3缺乏 name 属性而报错。
    报错
  • 针对于此,我们可以了解到,name属性是必须的,但是各个name有不同(属性的私有性),所以难免的我们再添加name的时候容易遗忘。那么我们就可以运用特殊方法__init__(),对代码进行改进。从而减少这种报错。
#改进前
class Person():
    name = '李云龙'
    def Speak(self):
         print('%s的意大利炮'%self.name)
         print('{}的意大利炮'.format(self.name))
n1 = Person()
n1.Speak()
# 改进中
class Person():
    def __init__(self):
        self.name = '李云龙'

    def Speak(self):
        print('%s的意大利炮' % self.name)
        print('{}的意大利炮'.format(self.name))

n1 = Person()
n1.Speak()

改进对照

  • 虽然两个代码块输出的值相同,但是其内部却发生了大变化。
  • 改进前的name属性代码如果忘了添加,则会报错,而改进中的代码相当于是n1的私有代码,相当于进行了一个赋值操作。减少了这种报错,但是从图我们也可以看出,虽然使用了魔术方法,但是,代码输出形式依然单一,如果输出其他人需要对name属性进行更改。由此,我们诞生了一个问题,可否更好的‘私有赋值’?

思考一下,我们实现“私有赋值”,其实就是调用自己,那么,我们把上面代码

    def __init__(self):
        self.name = '李云龙'

中的“李云龙”,改为实例对象赋值的name岂不是就可以了? 改法如下:
改进后01

  • 由代码报错可得,第58行缺失一个参数。其实缺失的参数就是name(李云龙)
# #改进后
class Person():
    def __init__(self,name):
        self.name = name

    def Speak(self):
        print('%s的意大利炮' % self.name)

n1 = Person('李云龙')
n1.Speak()

改进后02

3.类的基本结构

#类的基本结构
class 类名([父类]):

    公共属性...

    #对象的初始化方法
    def __init__(self、...):
    
        代码块

    #对象的其他方法
    def method1(self、...):
    
        代码块

    ...
    

类的基本结构

二.封装

1.封装的引入

值的改变

  • 当我们在其中加入一行代码时,再来看输出值
class Person():
    def __init__(self,name):
        self.name = name

    def Speak(self):
        print('%s的意大利炮' % self.name)

n1 = Person('李云龙')
n1.name = '春天'
n1.Speak()

值的改变

  • 之前博客写到我们对于属性的改变可以使用 对象.属性名 的形式对属性值进行改变。
  • 但是,你是否觉得,这些值改的太随便,太任意了?

\color{red}{现在我们需要一种方式来增强数据的安全性——封装}

  • 我们都知道,封装是⾯向对象的三⼤特性之⼀.
  • 封装就是隐藏对象中的一些属性或方法,这些属性或方法不希望被外界访问。
  • 通过封装 ,属性不能像之前那样可以随意更改
  • 通过封装 ,属性不能改为任意的值

2.封装方式

(1).属性名的修改

  • 我们通过对对象的属性名进行修改,从而提高数据的安全性(修改为外部不知道的属性名)
  • 举个栗子:
#属性名的修改
class Dog():
    def __init__(self,name):
        self.hidden_name = name
    def Speak(self):
        print('请叫我%s'%self.hidden_name)
d = Dog('金毛')
d.Speak()
d.name = '哈士奇'
d.Speak()
d.hidden_name = '哈士奇'
d.Speak()

属性名的更改

  • 不同于以往的代码书写方式,我们将平时所写的 self.name 改为了外部不知道的 self.hidden_name ,所以,在使用 d.name 对属性进行更改时,无法对属性进行更改。

(2).getter和setter方法的使用

  • 我们在进行属性的更改时,使用 getter和setter 方法使外部能够访问到属性并进行更改。
#getter和setter方法对属性进行更改
class Dog():
    def __init__(self,name):
        self.hidden_name = name

    def Speak(self):
        print('请叫我%s'%self.hidden_name)
#通过方法 get_name 获取name
    def get_name(self):
        return self.hidden_name

#通过方法 set_name 修改name
    def set_name(self,name):
        self.hidden_name = name
d = Dog('金毛')
d.Speak()
print(d.get_name())
d.set_name('萨摩耶')
d.Speak()

get和set的使用

(3).(__属性)方式的封装(一般不推荐)

  • 可以为对象属性使用双下划线的形式来进行封装,__XXX 。
  • __XXX是对象的隐藏属性,隐藏属性只能在类的内部进行访问,无法通过对象访问。
  • 隐藏属性其实是python自动给属性起了另外的名字,这个名字叫做( _类__属性名
class Dog():
    def __init__(self,name):
        self.__name = name

    def Speak(self):
        print('请叫我%s'%self.__name)

    def get_name(self):
        return self.__name

    def set_name(self,name):
        self.__name = name

d = Dog('哈士奇')
d.Speak()
# print(d.__name)   # AttributeError: 'Dog' object has no attribute '__name'
print(d._Dog__name) # 哈士奇

_类__属性名

  • 注:这种封装方式其实也是对属性名进行更改的方式,而且比较麻烦,不正规, 一般不推荐 使用 双下划线 形式进行属性的封装。

(4).(_属性)方式的封装

  • 一般对私有属性进行封装,都是以 _开头 的形式
class Dog():
    def __init__(self,name):
        self._name = name

    def Speak(self):
        print('请叫我%s'%self._name)

    def get_name(self):
        return self._name

    def set_name(self,name):
        self._name = name

d = Dog('哈士奇')
print(d._name)

(_属性)方式的封装

3.封装的作用

  • 使⽤封装,虽然增加了类在定义时的复杂程度,但也提高了数据的安全性。
    • 隐藏属性名,使调⽤者⽆法随意的修改对象中的属性。
    • 增加了getter()和setter()⽅法,很好控制属性是否只读。
    • 使⽤setter()设置属性,可以增加数据的验证,确保数据是正确的。
    • 使⽤getter()⽅法获取属性,使⽤setter()⽅法设置属性。可以在读取属性和修改属性的同时做⼀些其他的处理。

三.@property装饰器

1.装饰器的作用

  • 我们可以使⽤@property装饰器来创建只读属性。
  • @property装饰器会将⽅法转换为相同名称的只读属性。

2.装饰器的用法

class Person():
    def __init__(self,name):
        self._name = name
    @property
#我们通过@property来获取方法name的属性值,并把方法name作为属性名
    def name(self):
        print('获得了名字')
        return self._name
#通过setter方法对获取的属性值进行修改 格式为@属性名.setter
    @name.setter
    def name(self,name):
        print('修改了名字')
        self._name = name

p = Person('李云龙')
print(p.name)
p.name = '赵刚'
print(p.name)

装饰器的使用方法

  • 首先,通过 @property对方法name 进行 属性值的获取 (其实就是get_name),只不过是只读属性。然后将被装饰方法的名字作为属性名
  • 其次,通过 @属性名.setter 的方式(其实就是set_name) 对属性值进行修改(设置)
  • 最后,进行属性值的输出。

ps: 当然,还有一个deleter,没有说。其实用法与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

python的内置命令

引用结束

猜你喜欢

转载自blog.csdn.net/weixin_45095678/article/details/107215377
今日推荐