python之面向对象进阶2

封装、property装饰器

封装分为3种情况:封装对象的属性、封装类的属性、封装方法。

封装对象的属性:(在属性名前加双下划线__)

class Person:
    def __init__(self,height,weight,name,sex):
        self.__height = height  #私有对象属性:不在外面调它
        self.__weight = weight
        self.__name = name
        self.__sex = sex

    def bmi(self):
        return self.__weight / self.__height ** 2

    def tell_height(self):
        print(self.__height)

    def tell_weight(self):
        return self.__weight

    def set_weight(self,new_weight):
        if new_weight > 20:
            self.__weight = new_weight

egg = Person(1.7,125,'egon',None)
egg.tell_height()#在类内调
print(egg.__dict__)#查看类内的私有属性
print(egg._Person__height)#在类外调用

通过私有属性后,我们可以更好的确保属性数值不会随意修改。

封装属性我们可以在set——weight里约束属性值得更改

class Person:
    def __init__(self,height,weight,name,sex):
        self.__height = height  #私有对象属性:不在外面调它
        self.__weight = weight
        self.__name = name
        self.__sex = sex

    def bmi(self):
        return self.__weight / self.__height ** 2

    def tell_height(self):
        print(self.__height)

    def tell_weight(self):
        return self.__weight

    def set_weight(self,new_weight):
        if new_weight > 20:
            self.__weight = new_weight

egg = Person(1.7,125,'egon',None)
egg.tell_height()#在类内调
# print(egg.__dict__)#查看类内的私有属性
print(egg._Person__height)#在类外调用
egg.set_weight(105)
print(egg.tell_weight())

#私有属性:
# 在本类内就可以正常调用
# 在本类外就必须_类名__属性名调用,(不建议你调)

封装类的属性

class Goods:
    __discount = 0.8  #类的私有属性
    def __init__(self,name,price):
        self.name = name
        self.price = price
    def goods_price(self):
        return self.price * Goods.__discount

banana = Goods('banana',2)
print(banana.goods_price())#类内调用
# print(Goods.__dict__)#查看类的私有属性
print(Goods._Goods__discount)#在类外调用私有属性

封装对象的方法

class Foo:
    def __init__(self,height,weight):
        self.height = height
        self.weight = weight

    def tell_bmi(self):
        #体重/身高的平方
        return self.weight / self.__heightpow()

    def __heightpow(self):  #私有方法
        return  self.height * self.height

egon = Foo(1.7,125)
print(egon.tell_bmi())
print(Foo.__dict__)
print(egon._Foo__heightpow())  #类外调用方法

#私有的:类属性 对象属性 方法
#变成私有的 :__名字
#在类内都是照常使用
#在类外部就变形称为:_类名__名字

#定义私有~的原因
#不让外部的人瞎调,不让子类继承

封装的进阶

通过property装饰器把一个方法变成一个属性用

from math import pi
class Circle:
    def __init__(self,radius):
        self.radius = radius

    @property   #area = property(area)
    def area(self):
        return pi*self.radius*self.radius

    @property
    def perimeter(self):
        return 2*pi*self.radius
c = Circle(10)
print(c.area)
print(c.perimeter)
我们调用area方法和perimeter方法就像调用属性一样

上个牛逼的代码(缓存网页的,用面向对象的方法)

from urllib.request import urlopen
class Web_page:
    def __init__(self,url):
        self.url = url
        self.__content = None#私有对象属性

    @property
    def content(self):   #content 内容,相当于一个属性
        if self.__content:  #做了一个什么转换  _Web_page__content
            return self.__content
        else:
            self.__content = urlopen(self.url).read().decode(encoding='utf-8')  #做缓存
            return self.__content

mypage = Web_page('http://www.baidu.com')
print(mypage.content)
print(mypage.content)

计算传入数据的值

#计算传入的数据的值
class Num:
    def __init__(self,*args):
        print(args)
        if len(args) == 1 and (type(args[0]) is list or type(args[0]) is tuple):
            self.members = args[0]
        else:
            self.members = args

    @property
    def sum(self):
        return sum(self.members)

    @property
    def average(self):
        return self.sum/len(self.members)

    @property
    def min(self):
        return min(self.members)

    @property
    def max(self):
        return max(self.members)
nums = Num([1,2,3])
print(nums.sum)
# print(nums.average)
# print(nums.min)
# print(nums.max)
# num2 = Num(4,5,6)
# print(num2.sum)
# print(num2.average)
# print(num2.min)
# print(num2.max)

property装饰器(property、set、del方法)

class Goods:
    __discount = 0.8  #类的私有属性
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    @property
    def price(self):
      new_price=self.__price * Goods.__discount
      return  new_price
    @price.setter
    def price(self,new_price):
        if type(new_price) is int:
            self.__price = new_price
    @price.deleter
    def price(self):
        del self.__price

apple = Goods('apple',10)
print(apple.price)
apple.price = 20
print(apple.price)

总结

#@property把一个类中的方法 伪装成属性
#obj.func()
#obj.func  -->属性
#因为属性不能被修改
#@funcname.setter,来修改
#obj.func = new_value 调用的是被@funcname.setter装饰器装饰的方法

#被@property装饰的方法名必须和被@funcname.setter装饰的方法同名

#@funcname.deleter
#在执行del obj.func 的时候会调用被这个装饰器装饰的方法(同名)

 

                                      

原文地址:https://www.cnblogs.com/1a2a/p/7365625.html