python面向对象二

特殊方法(魔术方法)

  • 格式__方法__
  • 不需要我们自己调用,特殊方法在特殊的时候自动调用
class People():
    def __init__(self):
        print('init is executing')
p1 = People()
# init is executing

  1. 特殊方法什么时候调用?
  2. 特殊方法有什么用?
    对于People这个类name属性是必须的,并且每一个实例对象的name属性不一样
    我们想要修改打印出来的名字,就需要一个新的对象,name属性是手动添加的
    这样容易出错
class People():
    name = 'Batman'
    def Speak(self):
        print('你好我是%s'%self.name)
a = People()
a.Speak()
a.name = 'spiderman'
a.Speak()
# 你好我是Batman
# 你好我是spiderman

我们使用特殊方法
我们不把类内部写死,写入什么名字,就返回什么

对象的创建流程

p1 = Person

  1. 创建了一个变量p1
  2. 在内中创建了一个新的对象
  3. 执行类中的代码块中的代码(只在类中执行一次)
  4. __init__方法执行了
class People():
    # 特殊方法不需要我们自己调用
    # 特殊方法会在特殊的时候自己调用
    # init会在对象创建以后立即自动执行
    # init会向新创建的对象初始化属性
    def __init__(self,name):
        # 通过self向新创建的对象初始化属性
        self.name = name
    def Speak(self):
        print('你好我是%s'%self.name)
        
p1 = People('spiderman')
p1.Speak()
p2 = People('superman')
p2.Speak()
# 你好我是spiderman
# 你好我是superman

类的基本结构

class 类名([父类]):
公共属性…。
对象的初始化方法
def init(self,…)

尝试定义一个表示车的类

class Car():
    def __init__(self, name, color):
        self.name = name
        self.color = color
    def function(self):
        print('汽车启动了')
    def horn(self):
        print('%s滴滴滴'%self.name)
c = Car('BYD', 'black')
c.function()
c.horn()
print(c.function)
print(c.horn)
print(c.name, c.color)
c.name = 'Benz'
c.color = 'white'
c.function()
c.horn()
# 汽车启动了
# black的BYD滴滴滴
# <bound method Car.function of <__main__.Car object at 0x0000016E303ADA48>>
# <bound method Car.horn of <__main__.Car object at 0x0000016E303ADA48>>
# BYD black
# 汽车启动了
# Benz滴滴滴

要增加数据的安全性
1.属性不能随意修改(我允许你改才能改,不允许不能改)
2.属性不能改为任意的值
为此我们引入封装

封装

  • 封装是面向对象的三大特性之一(封装、多态、继承)
  • 封装指的是隐藏对象中一些不希望被外部访问到的属性或方法
class Cat():
    def __init__(self, name):
        self.name = name
d = Cat('英短')  
print(d.name)
d = Cat('小野猫')
print(d.name)
# 英短
# 小野猫

上面我修改了属性名name,d.name的属性就改变了,如果我不想让别人修改怎么办?
封装一

  • 将对象的属性名修改为一个外部不知道的名字
  • 该方法只能防君子不能防小人,事实上很难有一种办法将程序写死,不让别更改
class Cat():
    def __init__(self, name):
        self.hidden_name = name
d = Cat('英短')  
print(d.hidden_name)
d = Cat('小野猫')
print(d.name)
# 英短
# AttributeError: 'Cat' object has no attribute 'name'

  • 如果获取&修改对象当中的属性?
  • 我们提供一个getter和setter方法可以访问和修改属性,getter和setter是一种规范化
class Dog():
    def __init__(self, name, sex):
        self.hidden_name = name
        self.hidden_sex = sex
    def Shout(self):
        print('%s%s:汪汪汪'%(self.hidden_sex, self.hidden_name))
    def get_name(self):
        return self.hidden_name
    def get_sex(self):
        return self.hidden_sex
    def set_name(self, name):
        self.hidden_name = name
    def set_sex(self, sex):
        if sex == '公' or sex == '母':  # -----做一个判断,如果性别不满足公母,则不修改性别属性
            self.hidden_sex = sex
d = Dog('金毛', '母') # -----传入名字和性别
print(d.get_name()) # ----get方法,可以获取到属性
d.Shout()
d.set_name('哈士奇') #-----set方法,可以修改属性
print(d.get_name()) # ----get,获取新的属性
d.set_sex('公') # ------修改性别属性
print(d.get_sex()) # ----获取新的性别属性
d.Shout() # ---执行Shout方法
# 金毛
# 母金毛:汪汪汪
# 哈士奇
# 公
# 公哈士奇:汪汪汪

你会发现一个封装好的类,非常麻烦,原本可能只需要几行搞定的代码,现在却需要20行。写成一个类,在写的过程中非常麻烦,调用的时候非常简单,就像我们使用requests库一样,requests库是一个对象,我们不需关心该对象是怎么创建的,我们只需知道它有什么功能。

封装二

  • 可以为对象的属性使用双下划线开头__xxx
  • 双下滑线开头的属性是对象的隐藏属性,隐藏属性只能在类的内部访问,不支持外部访问
  • 隐藏属性是python自动为属性改了一个名字
  • 实际上改的名字是:_类名__属性名 __name–>_Hero__name
class Hero():
    def __init__(self, name):
        self.__name = name
    def Sing(self):
        print('%s:i\'ve benn reading books of old'%self.__name)
    def get_name(self):
        return self.name
    def set_name(self, name):
        self.__name = name
h = Hero('Achilles')
h.Sing()
h.name = 'Hercules'
h.Sing()
h._Hero__name = 'spiderman'
h.Sing()
# Achilles:i've benn reading books of old
# Achilles:i've benn reading books of old
# spiderman:i've benn reading books of old

一般我们不适用__name 的形式,通常我们使用_name 一个下划线,表示该属性是私有属性,没有特殊情况下不要修改

@property

用来将一个get方法 转换成属性
添加@property装饰器后,我们就可以像调用一个属性一样调用一个方法

class Myth():
    def __init__(self, name):
        self._name = name
    def Song(self):
        print('the legend and the myth')
    @property
    def get_name(self):
        print('我是一个方法,但不需加括号就可以显示我')
        return self._name
    @get_name.setter
    def set_name(self,name):
        self._name = name
m = Myth('batman')
m.get_name
m.name = 'zeus'
print(m.name)
# 我是一个方法,但不需加括号就可以显示我
# zeus

里面加入了@set_name.setter,可以向修改属性一样使用set方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值