封装

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要

接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代

码改变不足为虑。

class Room:
    def __init__(self,name,length,width):
        self.name = name
        self.__length = length
        self.__width = width
        
    def get_name(self):
        return self.__name
    def set_name(self,newName):
        if type(newName) is str and newName.isdigit() ==False
            self.__name = newName
        else:
            print('不合法的姓名')
    def area(self):
        return self.__length * self.__width

s = Room('sole',2,1)
print(s.area())
'''
会用到私有的这个概念的场景
1.隐藏起一个属性 不想让类的外部调用
2.我想保护这个属性 不想让属性随意被改变
3.我想保护这个属性 不想让子类继承
'''

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

'''
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
  体质指数(BMI)=体重(kg)÷身高^2(m)
  EX:70kg÷(1.75×1.75)=22.86
'''
class Person:
    def __init__(self,weight,height):
        self.weight = weight
        self.height = height
    @property
    def bmi(self):
        return  self.weight/self.height**2
b1 = Personi(90,1.80)
print(b1.bmi)
import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2 #计算面积

    @property
    def perimeter(self):
        return 2*math.pi*self.radius #计算周长

c=Circle(10)
print(c.radius)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
314.1592653589793
62.83185307179586
注意:此时的特性area和perimeter不能被赋值
c.area=3 #为特性area赋值
抛出异常:
AttributeError: can't set attribute
'''

property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则.

class Foo:
    def __init__(self,val):
        self.__NAME=val #将所有的数据属性都隐藏起来

    @property
    def name(self):
        return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)

    @name.setter
    def name(self,value):
        if not isinstance(value,str):  #在设定值之前进行类型检查
            raise TypeError('%s must be str' %value)
        self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter
    def name(self):
        raise TypeError('Can not delete')

f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'
class Foo:
    def get_AAA(self):
        print('get的时候运行我啊')

    def set_AAA(self,value):
        print('set的时候运行我啊')

    def delete_AAA(self):
        print('delete的时候运行我啊')
    AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应

f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

classmethod

class Classmethod_Demo():
    role = 'dog'

    @classmethod
    def func(cls):
        print(cls.role)

Classmethod_Demo.func()

staticmethod

class Staticmethod_Demo():
    role = 'dog'

    @staticmethod
    def func():
        print("当普通方法用")

Staticmethod_Demo.func()

在完全面向对象的程序中,

如果一个函数 即和对象没关系 也和类没有关系 

那么就用staticmethod将这个函数方法变成一个静态方法类方法和静态方法 都是类调用的

对象可以调用类方法和静态方法 一般情况下

推荐用类名调用类方法 有一个默认参数 cls 代表这个类 

静态方法 没有默认的参数 就象函数一样

 

posted on 2018-01-19 16:02  Kindergarten_Panda  阅读(139)  评论(0编辑  收藏  举报