python之路_面向对象三大特性之封装

1、私有属性

(1)动态属性

  在python中用双下划线开头的方式将属性隐藏起来。类中所有双下划线开头的名称,如__x都会自动变形成:_类名__x的形式。这种自动变形的特点是:

  a.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。b.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。c.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

class Teacher:
    def __init__(self,name,pswd):
        self.name=name
        self.__pswd=pswd                                       #私有属性
    def func(self):
        print(self.__pswd)
alex=Teacher('alex','3714')
alex.func()
# print(alex.__pswd)                                           #私有属性不可以通过此方式查看
print(alex._Teacher__pswd)                                     #私有属性外部查看的方式:_Teacher__pswd储存

(2)静态属性

  私有化的方式同样为在属性名前加双下划线,只能在内部进行使用,外部查看方式与动态属性一样。

class Teacher:
    __identifier='teacher'                                     #私有静态属性
    def __init__(self,name,pwd):
        self.name=name
        self.__pwd=pwd                                         #私有属性
    def func(self):       
        print(self.__pwd,Teacher.__identifier)
print(Teacher._Teacher__identifier)                            #在外面查看静态属性方法
alex=Teacher('alex','1234')
alex.__a='aaa'                                                 #在外部定义,并不会形成私有化,__a即为一个合法的正常变量名
print(alex.__dict__)                                           #查看动态属性字典,结果为:{'name': 'alex', '_Teacher__pwd': '1234', '__a': 'aaa'}

问题点总结:

  (a).这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N。

  (b).“__属性”变形到“_类名__属性”只在类的内部生效,在定义后的进行的近似私有化赋值操作,不会变形,为正常的赋值过程。

2、私有方法

  私有化方法也只能在类的内部进行进行使用,有一些方法的返回值只是用来作为中间结果,可以进行私有化,如下例:

class Teacher:
    def __init__(self,name,pwd):
        self.name=name
        self.__pwd=pwd                                    #私有属性
    def __func(self):                                     #私有方法
        return hash(self.__pwd)
    def login(self,password):
        return hash(password)==self.__func()

alex=Teacher('alex','1234')
ret=alex.login('2234')
print(ret)                                                #输出结果为:False    

  在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的。

class Foo:
    def __jinghong_sb(self):                             #变形为:_Foo__jinghong_sb
        print('Foo')
class Son(Foo):
    def __jinghong_sb(self):                             #变形为:_Son__jinghong_sb
        print('Son')
    def func(self):
        self.__jinghong_sb()                             #变形为:_Son__jinghong_sb,

son = Son()
son.func()                                               #结果为:son

3、property方法

  实现类中的方法时,以查看类的属性的方式进行,即将类中的方法看起来像属性而不是方法。如下例:

#例1:
class
Person: def __init__(self,name,height,weight): self.name = name self.__height = height self.__weight = weight @property def bmi(self): return self.__weight / (self.__height**2) jinghong = Person('景弘',1.8,94) print(jinghong.name,jinghong.bmi) #输出结果:景弘 29.012345679012345

 

#例2:
import math
class Circle:
    def __init__(self,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)                                    #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值

  将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。以上不可以通过赋值对jinghong.bmi、c.area、c.perimeter进行更改。一个静态属性property本质就是实现了get,set,delete三种方法,具体实例如下:

class Shop:
    discount = 0.75
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    @property          
    def price(self):
        return self.__price * Shop.discount
    @price.setter      
    def price(self,new_price):
        self.__price = new_price
    @price.deleter
    def price(self):
        del self.__price

apple = Shop('apple',5)
print(apple.price)                                   #获取商品价格
print(apple.__dict__)                                #输出结果:{'name': 'apple', '_Shop__price': 5}
apple.price = 6                                      #修改商品原价
print(apple.price)
print(apple.__dict__)                                #输出结果:{'name': 'apple', '_Shop__price': 6}
del apple.price                                      #删除商品原价
print(apple.__dict__)                                #输出结果:{'name': 'apple'}
  注意:只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter,如上例且各属性方法名需一样,均为price。
4、classmethod和staticmethod
  (1)普通方法:
必须传一个对象 可以使用对象的属性和类的属性
class A:
    def __init__(self,name):
        self.name = name

    def func(self):                                 #普通方法,self为形式参数
        print( self.name)
  (2)类方法(classmethod):必须传一个类,方法不需要使用对象的属性,但可以使用类的属性
class A:
    role = 'a'
    @classmethod
    def class_method(cls):                          #类方法,cls代表类
        print(cls.role)
A.class_method()                                    #输出结果:a类名.方法名()调用

  (3)静态方法(staticmethod):没有必须传的参数,方法不需要用对象的属性和类的属性

class Staticmethod_Demo():
    role = 'dog'
    @staticmethod
    def func():                                   #静态方法,不需要参数
        print("a")
Staticmethod_Demo.func()                          #调用方式:类名.方法名()
  使用情况:不能将函数独立的放在类外面 完全使用面向对象编程的时候,并且这个函数完全不需要依赖对象的属性和类的属性, 就可以用staticmethod装饰这个函数。
 

 

 

 

 
 

 

posted @ 2017-09-20 17:02  骑猪走秀  阅读(170)  评论(0编辑  收藏  举报