zoukankan      html  css  js  c++  java
  • 封装,property装饰器,绑定方法

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

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

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

    3、如何封装

    # 如何隐藏:在属性前加上__开头
    #1、 这种隐藏仅仅只是一种语法上的变形操作
    #2、 这种语法上的变形只在类定义阶段发生一次,因为类体代码仅仅只在类定义阶段检测一次
    #3、 这种隐藏是对外不对内的,即在类的内部可以直接访问,而在类的外则无法直接访问,原因是
    # 在类定义阶段,类体内代码统一发生了一次变形
    #4、 如果不想让子类的方法覆盖父类的,可以将该方法名前加一个__开头

    # class People:
    #     __country="China"
    #     def __init__(self,name,age,sex):
    #         self.__name=name
    #         self.age=age
    #         self.sex=sex
    #
    #     def eat(self):
    #         print("eat....")
    #         print(People.__country)#凡是在内部进行查看都时没问题,
    #         print(self.__name)     #因为在定义的时候都一起发生改变
    #
    #
    # obj=People("yf",18,"mael")
    # obj.eat()              #这是访问类内部的函数名,所以内部访问可以看见
    # print(People.__country)#当类的数据变量名被隐藏的时候直接去访问时看不见
    # print(People.eat(123)) #当类去访问其内部的函数间接访问该内容的时候可以看得见
    # print(obj.__name)
    # People.__x=11          #因为时在定义阶段进行封装发生一次,所以后面就算添加进去也只是其添加时形态__x
    # print(People.__dict__) #通过查看类的内部情况可以看见,所有被隐藏的属性,都
    # 是在前面变化成 _类名 的形式
    # print(People._People__country)#按照其封装方式 _类名__属性 的形式时可以查到
    # peo1=People("egon",18,"male")
    # print(peo1.__dict__)
    # peo1.__111
    # print(peo1.__dict__)
    # class Foo:
    #     def __f1(self):
    #         print("Foo.f1")
    #
    #     def f2(self):
    #         print("Foo.f2")
    #         self.__f1()
    #
    # class Bar(Foo):
    #     def __f1(self):
    #         print("Bar.f1")
    #
    # obj=Bar()
    # obj.f2()
    #在没隐藏的状态下显示Foo.f2   Bar.f1
    #如果隐藏子类
    #显示 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))
    #         # self.set_info(self.__name,self.__age)
    #     def set_info(self,name,age):
    #         if type(name) is not str:
    #             raise TypeError("用户名必须为str类型")#主动报错方式,是自己设置的内容,
    #             # 代替了print与return
    #         if type(age) is not int:
    #             raise TypeError("年龄必须为int类型")
    #
    #         self.__name=name#当逻辑判断都通过的时候就可以更改属性
    #         self.__age=age
    
    
    # peo1=People("egon",18)
    # peo1.tell_info()
    # #首先定义属性的目的就是为了给类外部的使用使用的
    # # 隐藏之后是为了不让外部使用直接使用,需要类内部开辟一个接口
    # #然后让类外部的使用通过接口来间接的操作是隐藏的属性
    # #精髓在于:我们可以再接口上附加任意逻辑,从而严格控制使用者对属性的操作
    # peo1.set_info("egon",19)
    # peo1.tell_info()
    # peo1.__name=123#经过隐藏后,要像直接修改属性的姓名密码,都是不会成功,
    # 除非是按照改变方式作死的去改
    # peo1.age=22
    # peo1.tell_info()
    封装数据属性的用途
    class ATM:
        def __card(self):
            print('插卡')
        def __auth(self):
            print('用户认证')
        def __input(self):
            print('输入取款金额')
        def __print_bill(self):
            print('打印账单')
        def __take_money(self):
            print('取款')
    
        def withdraw(self):
            self.__card()
            self.__auth()
            self.__input()
            self.__print_bill()
            self.__take_money()
    
    a=ATM()
    a.withdraw()
    封装函数的用途

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

    # 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)
    #
    # peo1=People("yf",68,1.75)
    # print(peo1.bmi)
    # peo1.height=1.85#通过更改身高,对象使用bmi属性可以达到改变的效果,表示property装饰器有效
    # print(peo1.bmi)
    property装饰器
    # class People:
    #     def __init__(self,name):
    #         self.name=name
    #
    #     @property
    #     def name(self):
    #         return "<名字是:%s>" %self.__name
    #
    #     @name.setter
    #     def name(self,name):
    #         if type(name) is not str:
    #             raise TypeError("名字必须是str类型")
    #         self.__name=name
    #
    #     @name.deleter
    #     def name(self):
    #         del self.__name
    #
    # peo1=People("egon")
    # print(peo1.name)
    #
    # peo1.name="Egon"#会自动判断进行的是修改或者查看,删除
    # print(peo1.name)
    #
    # del peo1.name
    # print(peo1.name)#如果没有property那么这些操作都是先按照最后一个对象属性的这个名字操作(这样就乱了)


    1、绑定方法
    特性:绑定给谁就应该由谁来调用,谁来调用就会讲谁当作第一个参数自动传入
    《精髓在于自动传值》
    绑定方法分为两类
    1.1绑定给对象方法
    在类内部定义的函数(没有被任何装饰器修改的),默认就是绑定给对象用的
    1.2绑定给类的方法
    在类内部定义的函数如果被装饰器@classmethod装饰,
    那么则是绑定给累的,应该由类来调用,类来调用就自动将类当作第一个参数自动传入
    2、非绑定方法
    类中定义的函数如果被装饰器@staticmethodz装饰,那么该函数就变成非绑定方法
    既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
    但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数

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

    # class Foo:
    #     @classmethod#绑定给类
    #     def f1(cls):#绑定给类的函数,内部会自动传入cls代表是跟类绑定
    #         print(cls)
    #     def f2(self):
    #         print(self)
    # obj=Foo()
    # print(obj.f2)
    # print(Foo.f1)
    # #1、f1绑定给类的
    # #了解:绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的任然是类
    # print(Foo.f1)#<bound method Foo.f1 of <class '__main__.Foo'>>
    # print(obj.f1)#<bound method Foo.f1 of <class '__main__.Foo'>>#对象调用类的绑定可以不用传值,但是类还是会自动传入,# 显示绑定给类的
    # Foo.f1()#<class '__main__.Foo'>
    # obj.f1()#<class '__main__.Foo'>
    #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))
    #         #类获取到外部导入的IP与PORT后直接通过对象进行查看
    #     @classmethod
    #     def from_conf(cls):
    #         return cls(settings.IP,settings.PORT)
    #         #因为是从外部导入内容,所以需要通过类导入进行获取
    #     @staticmethod#加上这个装饰器后变成普通函数
    #     def func():#这里面有几个形参,对象或者类调用就必须要有几个实参
    #         print("不与任何人绑定")
    #     @staticmethod
    #     def create_uid():#自动生成id,uuid生成的id每次都不一样
    #         return uuid.uuid1()
    # 
    # # 默认的实例化方式:类名(..)
    # obj=Mysql('10.10.0.9',3307)
    # # 一种新的实例化方式:从配置文件中读取配置完成实例化
    # # ojb=Mysql.from_conf()#类的传值基本都用于配置文件的读取
    # # ojb.tell_info()
    # 
    # #普通函数都可以直接使用,只是有几个参数就传几个,没有自动传入
    # # obj.func()
    # # Mysql.func()
    # # print(obj.func)
    # # print(Mysql.func)
    # 
    # print(obj.uid)#是调用对象内的id属性看id
    绑定的具体示范
  • 相关阅读:
    一、ThinkPHP的介绍
    一、ThinkPHP的介绍
    perl 爬虫两个技巧
    perl 爬虫两个技巧
    perl 爬取上市公司业绩预告
    perl lwp get uft-8和gbk
    perl lwp get uft-8和gbk
    perl 爬取同花顺数据
    perl 爬取同花顺数据
    php 接口示例
  • 原文地址:https://www.cnblogs.com/yf18767106368/p/9239546.html
Copyright © 2011-2022 走看看