Object-oriented packages and the decorative use @property

Package

1. Packaging definition

The complex ugly, privacy details hidden to the internal and external provides a simple to use interface that hides the external interface to the internal implementation details, and provide access;

2. The package Objective:

     封装的目的: 面向对象的核心是对象二字,精髓在于整合,封装的目的其实就是把一堆数据属性和方法属性整合到对象中,我们可以把对象比喻成一个容器,其实就是为了把数据存入一个容器中。存的目的就是为了取的,那封装到对象中的好处就是可以通过 "对象.属性" 的方式把属性取出来。 

3. The package of three ways

1.publish: for all public authority , where the outside can access.

2.protected: This is only in the current class, or inherit it " subclasses " (derived class) can access.

3.private: This package is equivalent to the privatization of property , so that no one can access. But the python is no mechanism to enforce this restriction, only to realize the privatization of property on the surface by limiting access mechanism

4. The advantage of the package

1. good encapsulation can be reduced coupling.

2. The internal structure of the class can be modified freely.

3. You can be more precise control of the member variables.

4. hidden information, the implementation details.

# 不封装
def login(name, pwd, root):
    if name == 'tank' and pwd == '123' and root == 'vip':
        print('登录成功!')
    else:
        print('登录失败!')

login('tank', '123', 'vip')

# 封装
class User:
    def __init__(self, name, pwd, root):
        self.__name = name
        self.__pwd = pwd
        self.__root = root

    def change_pwd(self, new_pwd):
        self.__pwd = new_pwd

    @property
    def get_name(self):
        return self.__name

    @property
    def get_pwd(self):
        return self.__pwd

    @property
    def get_root(self):
        return self.__root

user_obj = User('tank', '123', 'vip')

def login(obj):
    if obj.get_name == 'nim' and obj.get_pwd == '123' and obj.get_root == 'vip':
        print('登录成功!')

    else:
        print('登录失败')

user_obj.change_pwd('321')
login(user_obj)

The access restrictions (package)

Hidden object's properties and implementation details, only the external provision of public access.
Objective:
1. To ensure the security of critical data
2. External hide implementation details, the complexity of isolation

1) private variables

#其实这仅仅这是一种变形操作
#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

class A:
    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X=10 #变形为self._A__X
    def __foo(self): #变形为_A__foo
        print('from A')
    def bar(self):
        self.__foo() #只有在类内部才可以通过__foo的形式访问到.

#A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

This deformation features:

1. __x class defined for internal use only, such as self .__ x, is the result of deformation by reference;

2. This deformation fact, it is against external deformation is not accessible to the outside through __x name;

3. In a subclass definition __x not covered in the parent class definition __x, as a subclass morphed into: _ subclass name __x, while the parent class morphed into: _ parent class name __x that property at the time of the beginning of the double underscore inherited by subclasses, a subclass can not be covered.

This deformation problems that need attention are:

*** 1 This mechanism also does not limit us direct access from the outside property real sense, knowing the class name and property name can spell the name: class name _ __ property, then you can visit, such as a. _A__N ***

2. Modification of the process into effect only within the class, as defined in the assignment, is not deformed

>>> a=A()
>>> a.__dict__
{'_A__X':10}
>>> a.__Y = 1
>>> a.__dict__
{'_A__X':10,'__Y':1}

img

2) private method

In succession, the parent class if you do not want subclasses to cover their own methods, methods can be defined as private.

# 正常情况
class A:
   def fa(self):
       print('from A')
   def test(self):
       print(self)  # <__main__.B object at 0x00000000023A6FD0>
       self.fa()

class B(A):
   def fa(self):
       print('from B')

b=B()
b.test()

# 把fa定义成私有的,即__fa
class A:
     def __fa(self): #在定义时就变形为_A__fa
         print('from A')
     def test(self):
         print(self) # <__main__.B object at 0x00000000023A6FD0>
         self.__fa() #只会与自己所在的类为准,即调用_A__fa

class B(A):
     def __fa(self):
         print('from B')

b=B()
b.test()

Example 1:

img

#222  我们通过对__id_number进行修改,来对比外部是否能对__开头的属性进行修改.# p.show_id()  #12312  内部值并没有发生变化,所以通过__开头进行封装,外部通过普通方法并不能对内部的值进行修改.

Example 2:

  # 通过__方法名()的方式,将内部内部具体实现细节封装起来,只给外部暴露一个简单的开机(open函数)接口
  class PC: 
     def __init__(self,price,color,kind):
         self.color=color
         self.price=price
         self.kind=kind
     def open(self):
         print('接通电源')
         self.__check_device()
         print('载入内核')
         print('初始化内核')
         self.__start_service()
         print('启动GUI')
         self.__login()
 
     def __check_device(self):
         print('检测硬件1')
         print('检测硬件2')
         print('检测硬件3')
         print('检测硬件4')
     def __start_service(self):
         print('启动服务1')
         print('启动服务2')
         print('启动服务3')
     def __login(self):
         print('login..')
 
 pc=PC(6000,'white','lenvo')
 pc.open()
 '''
 接通电源
 检测硬件1
 检测硬件2
 检测硬件3
 检测硬件4
 载入内核
 初始化内核
 启动服务1
 启动服务2
 启动服务3
 启动GUI
 login..
 
 '''

Example 3:

# e.g.1
class Downloader:
    def __init__(self,filename,url,buffer_size):
        self.filename=filename
        self.url=url
        self.__buffer_size=buffer_size

    def start_download(self):
        if self.__buffer_size<=1024*1024:
            print('开始下载...')
        else:
            print('内存不足..')

d=Downloader('葫芦娃','http://www.baidu.com',1024*1024)

d.buffer_size=1024*1024*10  #类中__开头的属性无法直接访问,所以无法修改。
d.start_download()
'''
开始下载...
'''

# e.g.2
class Downloader:
    def __init__(self,filename,url,buffer_size):
        self.filename=filename
        self.url=url
        self.__buffer_size=buffer_size

    def start_download(self):
        if self.__buffer_size<=1024*1024:
            print('开始下载...')
            print('当前缓冲区大小为%s'%self.__buffer_size)
        else:
            print('内存不足..')

    def set_buffer_size(self,size):
        self.__buffer_size=size
    def get_buffer_size(self):
        return self.__buffer_size

d=Downloader('葫芦娃','http://www.baidu.com',1024*1024)


#通过函数去修改内部封装的属性
d.set_buffer_size(1024*1024/2)

#通过函数访问内部封装的属性
print(d.get_buffer_size())
d.start_download()


'''
524288.0
开始下载...
当前缓冲区大小为524288.0
'''

Example 4

class Foo:
    __name = 'rose'  # 变形成 _Foo__name
    def __init__(self,sex):
        self.__sex=sex

    @property
    def __sing(self):  # 变形成_Foo__sing,外部可以通过变形后的名字从外部直接访问。
        print('我是隐藏属性,不懂其变形情况在外部是无法访问的!')
       

f = Foo('male')
print(f._Foo__name)
f._Foo__sing

'''
rose
我是隐藏属性,不懂其变形情况在外部是无法访问的!

'''

@property decorator

@Property internal function for decoration: When @property make the object call a method, the object method () method to obtain the form of the object becomes the target point functions (methods) looks like a normal point data. attributes, making the same call mode. Remember: after the function name after the decorative brackets do not add it! ! !

On the way to modify the properties of the decoration @ key.setter Used
@ key.deleter the decoration is used in a method to delete a property

Note: key is the name of the decorated property method, which is the name of the property; interior creates an object variable name is the name of the function, so when using setter and deleter must ensure that objects to invoke methods, it is key.setter and key.deletter.

Example 1

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('tank')
# print(f.name)
# f.name = 10  # 抛出异常'TypeError: 10 must be str'
f.name = 'zhang' 
print(f.__dict__)  # {'_Foo__NAME': 'zhang'}
# del f.name #抛出异常'TypeError: Can not delete'

Example 2

class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
    @property
    def bmi(self):
        return self.weight / (self.height**2)

p1=People('egon',75,1.85)
print(p1.bmi)  #直接实例对象 点 方法名称就可以了

Example 3

class Goods:

    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price

    @price.setter
    def price(self, value):
        self.original_price = value

    @price.deleter
    def price(self):
        del self.original_price


obj = Goods()
obj.price         # 获取商品价格
obj.price = 200   # 修改商品原价
print(obj.price)
del obj.price     # 删除商品原价

Guess you like

Origin www.cnblogs.com/zhangchaocoming/p/11665888.html