python面向对象的封装、绑定方法

'''
一。封装
1、什么是封装
        封:属性对外是隐藏的,但对内是开放的
        装:申请一个名称空间,往里装入一系列名字、属性

2、为什么要封装
        封装数据属性的目的
            1 首先定义属性的目的就是为了给类外部的使用者使用的
            2 隐藏之后为了不让外部使用者直接使用,需要类内部开辟一个借接口
            3 然后让类外部的使用通过接口来间接的操作隐藏的属性
            4 精髓在于:我们可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作

        封装函数属性目的
            1首先定义属性的目的就是为了给类外部使用者使用的
            2 隐藏函数属性是为了不让外部直接使用,需要在内部开辟一个接口
            3 然后用接口去调用隐藏的功能
            4 精髓在于:隔离了复杂度

3、如何封装


如何隐藏:在属性前加上__开头

1 这种隐藏仅仅是一种语法上的变形操作
2 这种语法上的变形只是在类定义阶段发生一次,因为类体代码仅仅只在类的定义阶段检测一次
3 这种隐藏是对外不对内的,即再内的内部可以直接访问,而在类的外部则无法直接访问,
    原因是再类的定义阶段,类体代码统一发生了一次变形

4、如果不想让子类的方法覆盖父类的,可以在该方法名前加一个__开头

'''
# class People:
#     __country='china'#_People__coutry='china'
#
#     __n=100#_People__n=100
#     def __init__(self,name,age,sex):
#         self.__name=name #self._People__name=name
#         self.age=age
#         self.sex=sex
#
#     def eat(self):
#         print('eat .....')
#         print(People.__country) #People._People__courtry
#         print(self.__name) #self._People__name
#
# peo1=People('lin',18,'male')
# # People.eat(123)#间接调用
#
# # print(People.__country)#不能直接访隐藏的属性
#
# peo1.eat()#间接调用
# # print(peo1.__name)#无法直接操作
# #
# # print(People.__dict__)#查看属性的字典
# print(People._People__country)#利用存的语法方法可以查看,不过失去其隐藏的意义


# People.__x=1 #后加的值无法进行语法的变形

# print(People.__dict__)
#
# peo1=People('egon',18,'male')

# peo1.__x=111
# print(peo1.__dict__)#因为后加的没有语法变形,所以可以直接修改
#
# class Foo:
#     def __f1(self):#_Foo_f1
#         print('foo.f1')
#
#     def f2(self):
#         print('foo.f2')
#         self.__f1()#self._Foo__f1
#
# class Bar(Foo):
#     def __f1(self): #_Bar__f1
#         print('bar.f1')

#
# obj=Bar()
# obj.f2()
#先打印 foo.f2 后打印 foo.f1
#因为在类在定义阶段就将类体代码变形好了,所以只能在父类中找
# 如果不想让子类的方法覆盖父类的,可以在该方法名前加一个__开头


class People:
    def __init__(self,name,age):
        self.__name=name
        self.__age=age

    def tell_info(self):
        print('%s:%s'%(self.__name,self.__age))

    def set_info(self,name,age):
        if type(name) is not str:
            raise TypeError('用户名必须为str类型')

        if type(age) is not int:
            raise TypeError('年龄必须为int类型')

        self.__name=name
        self.__age=age

peo1=People('egon',18)
peo1.name=123  #新增的值 {'_People__name': 'egon', '_People__age': 18, 'name': 123}
# peo1.age  #不能直接找到隐藏的属性
peo1.tell_info()#通过间接调用接口
print(peo1.__dict__)

peo1.set_info('egon',19)

# peo1.tell_info() #通过接口将信息修改

# 二,property 装饰器
# 用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用

# class People:
#     def __init__(self,name,weight,height):
#         self.name=name
#         self.weight=weight
#         self.height=height
#
#     @property#直接将bmi伪装成数据属性直接 对象.函数名的方式
#     def bmi(self):
#         return self.weight/(self.height**2)
#
# peo1=People('egon',75,1.80)
# peo1.height=1.85 #更改值
# print(peo1.bmi)#用类的函数


# class People:
#     def __init__(self,name):
#         self.__name=name
#
#     @property #查看obj.name
#     def name(self):
#         return '<名字是:%s>'%self.__name
#
#     @name.setter  #修改obj.name=值 必须之前有@property装饰器才可
#     def name(self,name):
#         if type(name) is not str:
#             raise TypeError('必须为字符串类型')
#         self.__name=name
#
#     @name.deleter #删除 del obj.name  必须前有@property装饰器才可
#     def name(self):
#         # raise PermissionError('不能删')
#         del self.__name
#
# peo1=People('egon')
# print(peo1.name)
#
# peo1.name='lin'
# print(peo1.name)
#
# del peo1.name

class People:
    def __init__(self,name):
        self.__name=name

    def tell_name(self):
        return '<名字是:%s>'%self.__name
    def set_name(self,name):
        if type(name)is not str:
            raise TypeError('名字必须是str类型')
        self.__name=name

    def del_name(self):
        print('不让删除')

    name=property(tell_name,set_name,del_name)
    #不建议使用此方式

peo1=People('egon')
print(peo1.name)
peo1.name='egon'
print(peo1.name)
del peo1.name

'''
一。绑定方法和非绑定方法

1、绑定方法
    特性:绑定给谁就应该有谁来调用,谁来调用就会将谁当作第一个参数自动传入
     《 精髓在于自动传值》

     绑定方法分为两类:
         1 绑定给对象的方法
            在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的

         2 绑定给类的方法:
            在类内部定义的函数如果被装饰器@classmethod装饰,
            那么则是绑定给类的,应该由类来调用的,类来调用就自动将类当做第一个参数自动传入

2、非绑定方法
    类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法
    既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
    但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数


3、应用
    1.如果函数体代码需要用外部传入的类,则应该将函数定义成绑定给类的方法
    2.如果函数体代码需要用外部传入的对象,则应该将函数定义成绑定给对象的方法
    3.如果函数体代码即不需要外部传入的类也不需要外部传入的对象,则应该将函数定义成
    非绑定方法、普通函数

'''
# class Foo:
#     @classmethod  #给类建立绑定方法
#     def f1(cls):
#         print(cls)
#     def f2(self):
#         print(self)
#
# obj=Foo()
# print(obj.f2)
# print(Foo.f1)#;两个都建立了绑定方法
#
# Foo.f1()
# print(Foo)
#
# # 1、f1绑定给类的
# # 了解:绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的仍然是类
#
# print(Foo.f1)
# # print(obj.f1)
# Foo.f1()
# obj.f1()
# #
# # 2、f2是绑定给对象用的
# obj.f2()
# Foo.f2(obj)#在用的时候需自己传入参数

import settings
import uuid

class Mysql:
    def __init__(self,ip,port):
        self.uid=self.create_uid()
        self.ip=ip
        self.port=port
    def tell_info(self):
        print('%s:%s'%(self.ip,self.port))

    @classmethod
    def from_conf(cls):
        return cls(settings.IP,settings.PORT)

    @staticmethod
    def func(x,y):
        print('不与任何人绑定')
    @staticmethod
    def create_uid():
        return uuid.uuid1()
#
# 默认的实例化方式:类名(,,,)
obj=Mysql('10.10.1.9',3307)

#一种新的实例化方法:从配置文件中读取配置完成实例化

# obj1=Mysql.from_conf()
# obj1.tell_info()
#
# obj.func(1,3)
# Mysql.func(3,3)
#
# print(obj.func)
# print(Mysql.func)
#
# print(obj.uid)

猜你喜欢

转载自blog.csdn.net/qq_35540539/article/details/80849328