Python零基础之面向对象(__init__方法,封装,property装饰器)

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()
    • 作用是把方法转换为同名的属性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kingx3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值