程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

yield(0)

面向对象(0)

标签  

字典(0)

列表(0)

日期归档  

Python学习日记(二十六) 封装和几个装饰器函数

发布于2019-09-09 09:59     阅读(798)     评论(0)     点赞(4)     收藏(4)


封装

广义上的封装,它其实是一种面向对象的思想,它能够保护代码;狭义上的封装是面向对象三大特性之一,能把属性和方法都藏起来不让人看见

私有属性

私有属性表示方式即在一个属性名前加上两个双下划线

复制代码
class Fighter:
    def __init__(self,name,hp,atk,speed):
        self.name = name
        self.__hp = hp                      #私有属性  变形成self._Fighter__hp
        self.__atk = atk                    #私有属性  变形为self._Fighter__atk
        self.__speed = speed                #私有属性  变形为self._Fighter__speed
f1 = Fighter('AKK-18',1500,200,300)
print(f1.__dict__)                          #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300}
复制代码

python的私有属性只是在代码的级别给加了一层密,不允许你直接去访问这些私有属性,像你去打印一个私有属性它的结果就是报错,或者你想尝试修改一个私有属性的时候,结果并不能修改成功

f1.__hp = 1000
print(f1.__dict__)                          #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300, '__hp': 1000}

因为上面的私有属性都已经变形成_类名__属性名的格式,我们这样写,相当于直接给self添加了一个新的'键名'__hp,所以在类的外部调用双下划线就不行

那如何访问我们的私有属性呢?我们可以看到上面的私有属性都被变形成了_类名__属性名的形式,那么我们可以这样去访问:

print(f1._Fighter__hp)                      #1500
print(f1._Fighter__atk)                     #200
print(f1._Fighter__speed)                   #300

但光这样走这样的捷径是不完美的,我们可以在类内部添加一个get_value函数来获得那些私有属性

复制代码
class Fighter:
    def __init__(self,name,hp,atk,speed):
        self.name = name
        self.__hp = hp                      #私有属性
        self.__atk = atk                    #私有属性
        self.__speed = speed                #私有属性
    def get_value(self):
        return self.__hp,self.__atk,self.__speed        #只要在类内部使用私有属性就会自动带上'_类名’
f1 = Fighter('AKK-18',1500,200,300)
print(f1.__dict__)                          #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300}
print(f1.get_value())                       #(1500, 200, 300)
for i in f1.get_value():
    print(i)                                #1500
                                            #200
                                            #300
复制代码

在get_value中return的写法其实就是变形后再获取私有属性

def get_value(self):
    return self._Fighter__hp,self._Fighter__atk,self._Fighter__speed

私有静态属性

复制代码
class Fighter:
    __id = 1234445                          #私有静态属性
    def __init__(self,name,hp,atk,speed):
        self.name = name
        self.__hp = hp                      #私有属性
        self.__atk = atk                    #私有属性
        self.__speed = speed                #私有属性
    def get_value(self):                    #获取内部私有属性方法
        return self.__hp,self.__atk,self.__speed
    def get_id(self):
        return self.__id
f1 = Fighter('AKK-18',1500,200,300)
print(f1._Fighter__id)                      #1234445
print(f1.get_id())                          #1234445
复制代码

私有方法

复制代码
class Fighter:
    __id = 1234445                          #私有静态属性
    def __init__(self,name,hp,atk,speed):
        self.name = name
        self.__hp = hp                      #私有属性
        self.__atk = atk                    #私有属性
        self.__speed = speed                #私有属性
    def get_value(self):                    #获取内部私有属性方法
        return self.__hp,self.__atk,self.__speed
    def get_id(self):                       #获取静态属性id的方法
        return self.__id
    def __shoot(self):                      #私有方法
        print('Shooting!')
    def get_shoot(self):                    #获取私有方法shoot
        self.__shoot()                      
        #self._Fighter__shoot()
f1 = Fighter('AKK-18',1500,200,300)
f1.get_shoot()                              #Shooting!
复制代码

修改私有属性

复制代码
class Room:
    def __init__(self,name,length,width):
        self.__name = name
        self.__length = length
        self.__width = width
    def Area(self):
        return self.__width*self.__length
    def get_name(self):         #获取这个私有名字的方法
        return self.__name
    def set_name(self,new_name):#重新设定这个房号
        if type(new_name) is str and new_name.isdigit() == True:
            self.__name = new_name
        else:
            print('错误的命名方式!')
r1 = Room('1101',15,20)
print(r1.Area())                #300
print(r1.get_name())            #1101
r1.set_name('asd')
print(r1.__dict__)              #{'_Room__name': '1103', '_Room__length': 15, '_Room__width': 20}
print(r1.get_name())            #1103
复制代码

 

几个装饰器

1.@property

我们在用面向对象的思想去写一个圆经常会把它的周长和面积当成一个方法,然而我们知道方法是一个获取的动作,而不是一个属性名词,所以要想处理这种将一个方法伪装成为一个属性就要用到@property,这样这个方法它就看起来像是一个属性了

复制代码
from math import pi as P
class Circle:
    def __init__(self,r):
        self.r = r
    def Perimeter(self):
        return 2*P*self.r
    def Area(self):
        return P*self.r**2
c = Circle(5)
print(c.Area())                     #78.53981633974483
print(c.Perimeter())                #31.41592653589793
复制代码

改进:

复制代码
from math import pi as P
class Circle:
    def __init__(self,r):
        self.r = r
    @property
    def Perimeter(self):        #这里在self的后面不能传任何参数
        return 2*P*self.r
    @property
    def Area(self):             #这里在self的后面不能传任何参数
        return P*self.r**2
c = Circle(5)
print(c.Perimeter)              #31.41592653589793
print(c.Area)                   #78.53981633974483
复制代码

BMI问题:BMI指数(BMI)=体重(kg)÷身高^2(m)

    成人的BMI数值:

    过轻:低于18.5

    正常:18.5-23.9

    过重:24-27

    非常肥胖:>32

复制代码
class BMI:
    def __init__(self,height,weight):
        self.__height = height
        self.__weight = weight
    @property
    def __bmi(self):                        #把计算bmi的方法伪装成一个属性
        return self.__weight/self.__height**2

    def get_bmi(self):                      #BMI判断
        if self.__bmi > 32:
            print('非常肥胖!')
        elif 24 <= self.__bmi <= 27:
            print('过重!')
        elif 18.5 <= self.__bmi <= 23.9:
            print('正常!')
        else:
            print('过轻!')

b = BMI(1.75,72)
b.get_bmi()                                 #正常!
复制代码
在@property的前提下用@setter来修改属性
复制代码
class Person:
    def __init__(self,name,):
        self.__name = name
    @property
    def name(self):
        return self.__name + ' hello!'
    @name.setter
    def name(self,new_name):
        self.__name = new_name
p1 = Person('Jogn')
print(p1.name)                               #Jogn hello!
#p1._Person__name = 'Maria'                  #Maria hello!
print(p1.name)                               #Maria hello!
复制代码
在@property的前提下用@deleter来删除属性
复制代码
class Person:
    def __init__(self,name,):
        self.__name = name
    @property
    def name(self):
        return self.__name + ' hello!'
    @name.deleter
    def name(self):                     
        del self.name                       
p1 = Person('Jogn')
print(p1.name)                               #Jogn hello!
del p1.name                                  #del p1.name它在这里的作用是指向deleter下面这个方法,再去做这个方法的功能
print(p1.name)                               #找不到这个名字了
复制代码

我们可以看一下在这里的del关键字它起到了什么的作用

复制代码
class Person:
    def __init__(self,name,):
        self.__name = name
    @property
    def name(self):
        return self.__name + ' hello!'
    @name.deleter
    def name(self):
        print('执行了这个方法!')
p1 = Person('Jogn')
print(p1.name)                               #Jogn hello!
del p1.name                                  #del p1.name它在这里的作用是指向deleter下面这个方法,再去做这个方法的功能
print(p1.name)                               #Jogn hello!
复制代码

因为第二个name里面没有关于修改名字的操作所以在最后p1.name还能打印出原来的名字

2.@classmethod

当这个方法只涉及到静态属性的时候,就应该使用classmethod来装饰这个方法

复制代码
class Goods:
    __discount = 0.8                                    #折扣
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    @property
    def price(self):
        return self.__price * self.__discount
    @classmethod
    def change_discount(cls,new_discount):              #cls为类名
        cls.__discount = new_discount                   #修改折扣
apple = Goods('苹果',4)
print(apple.price)                                      #3.2
Goods.change_discount(0.5)
print(apple.price)                                      #2.0
复制代码

3.@staticmethod

在完全面向对象的程序中,如果一个函数和对象没有关系那么就用staticmethod把这个函数变成一个静态方法

复制代码
class Login:
    def __init__(self,name,password):
        self.name = name
        self.password = password
    @staticmethod
    def get_n_psw():                            #没有默认参数就像函数一样
        username = input('请输入用户名:')
        psw = input('请输入密码:')
        Login(username,psw)                     #请输入用户名:asdd                                               
        return username,psw                     #请输入密码:4564648
print(Login.get_n_psw())                        #('asdd', '4564648')
复制代码


所属网站分类: 技术文章 > 博客

作者:goodbody

链接:https://www.pythonheidong.com/blog/article/103661/aeb460056f04d17d5d2c/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

4 0
收藏该文
已收藏

评论内容:(最多支持255个字符)