zoukankan      html  css  js  c++  java
  • Python学习笔记26:封装、@property、@staticmethod和@classmethod装饰器方法、反射getattr()

    学习参考Eva-J女神姐姐的博客:https://www.cnblogs.com/Eva-J/,如有侵权,请联系删除!

    封装

    知识点整理:

    # 会用到私有的这个概念de场景
    #1.隐藏起一个属性 不想让类的外部调用
    #2.我想保护这个属性,不想让属性随意被改变
    #3.我想保护这个属性,不被子类继承

    #私有后的属性,可以定义方法get_name实现调用
    #私有后的属性,可以定义set_name实现修改
    #父类的私有属性,不能被子类调用
    #
    # step1
    # class Room:
    #     def __init__(self,name,length,width):
    #         self.name = name
    #         self.__length = length
    #         self.__width = width
    #
    #     def area(self):
    #         return self.__length * self.__width
    #
    # jin = Room('金老板',2,1)
    # print(jin.area())
    
    # step2
    # class Room:
    #     def __init__(self,name,length,width):
    #         self.__name = name
    #         self.__length = length
    #         self.__width = width
    #
    #     def area(self):
    #         return self.__length * self.__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('不合法的姓名')
    #
    # jin = Room('金老板',2,1)
    # print(jin.area())
    # print(jin.get_name())
    # jin.set_name('2')
    # print(jin.get_name())
    
    # step3
    # 假设父类的私有属性,能被子类调用吗?不能
    # class Foo:
    #     __key = '123'   # _Foo__key
    #
    # class Son(Foo):
    #     print(Foo.__key)  # _Son__key
    
    

      

    @property装饰器

    知识点整理:

    # @property 用来对属性进行一些操作,如上面例子中的打折,那么这时候就可以把这个属性设置成
    # 私有的,然后在调用@property来设置一个和属性同名的方法,在该方法中实现对属性的操作,且该方法的调用和类中属性的调用方式一样,属性的调用不用方法后面的括号
    # 类中的属性值都是可以进行修改的,但是加入了@property装饰器的方法,不能进行修改,如果要进行修改,需要在加一个装饰器@属性_setter
    # 本来类中不能加入同名字的方法,加入@name.setter后可以,还可以新增一个参数
    # 如果要对属性进行删除,需先私有化,加上@property装饰器和@属性_deleter
    # step1
    # from math import pi
    # class Circle:
    #     def  __init__(self,r):
    #         self.r = r
    #
    #     @property  # 把perimeter伪装为一个属性
    #     def perimeter(self):
    #         return  2*pi*self.r
    #
    #     @property  # 把area伪装为一个属性
    #     def area(self):
    #         return self.r**2*pi
    #
    # c1 = Circle(5)
    # print(c1.area())  # 圆的面积应该是一个属性,但是却又是通过计算得到,如何把面积伪装为一个属性
    # print(c1.perimeter())
    # 加入装饰器后调用方式要改变
    # print(c1.area)  # 属性的调用不用方法后面的括号
    # print(c1.perimeter)
    
    
    # step2
    # 计算人的BMI指数
    # class Person:
    #     def __init__(self,name,high,weight):
    #         self.name = name
    #         self.high = high
    #         self.weight = weight   # 此处是属性的赋值,不要参与计算
    #
    #     @property
    #     def bmi(self):
    #         return self.weight / self.high ** 2
    #
    # jin = Person('金老板',1.6,90)
    # print(jin.bmi())
    # print(jin.bmi) # 加入装饰器后调用方式和属性的调用方式相同
    # 改名
    # jin.name = '222' # 此处可以修改属性,
    # print(jin.name)
    # jin.bmi = 18  #不能修改加入了装饰器后面的方法
    # jin.high = 1.8  # 可以修改属性
    # print(jin.high)
    # print(jin.bmi)
    
    # step3
    # class Person:
    #     def __init__(self,name):
    #         self.__name = name
    #
    #     @property  # 要用name.setter ,必须要先有property装饰器
    #     def name(self):
    #         return self.__name + 'sb'
    #
    #     @name.setter  # 本来类中不能加入同名字的方法,加入@name.setter后可以,还可以新增一个参数
    #     def name(self,newname):
    #         self.__name = newname
    #
    # tiger = Person('嗷嗷')
    # print(tiger.name)  # 此时name不能在继续修改
    # tiger.name = '欠缺'
    # print(tiger.name)
    
    
    # step4
    # class Goods:
    #     discount = 0.5
    #     def __init__(self,name,price):
    #         self.name = name
    #         self.__price = price
    #
    #     @property
    #     def price(self):
    #         return self.__price * Goods.discount
    #
    # apple = Goods('苹果',5)
    # print(apple.price)
    
    # @property 用来对属性进行一些操作,如上面例子中的打折,那么这时候就可以把这个属性设置成
    # 私有的,然后在调用@property来设置一个和属性同名的方法,在该方法中实现对属性的操作
    
    # step5
    # 属性可以查看、修改、删除
    # class Person:
    #     def __init__(self,name):
    #         self.__name = name
    #
    #     @property  # 私有化一个属性方法
    #     def name(self):
    #         return self.__name
    #
    #     @name.deleter
    #     def name(self):
    #         del self.__name
    #
    # a = Person('aaa')
    # print(a.name)
    # del a.name
    # print(a.name)
    

      

    @stacticmethod和 @classmethod

    知识点整理:

    # 当这个方法的操作只设计静态属性的时候,就应该使用classmethod来装饰这个方法,这个方法就可以直接被类来直接调用
    # 在完全面向对象的程序中,如果一个函数类还有对象都没关系,那么就用staticmethod将这个函数变成一个静态方法
    # step1
    # class Goods:
    #     __discount = 0.8  # 手动改的方式修改成一个方法
    #     def __init__(self,name,price):
    #         self.name = name
    #         self.__price = price
    #
    #     @property
    #     def price(self):
    #         return self.__price * Goods.__discount
    #
    #     @classmethod # 把下面的方法变成了类里面的方法,这个方法就直接可以被类调用,不需要依托任何对
    #     def change_discount(cls,new_discount):
    #         cls.__discount = new_discount
    #
    # a = Goods('苹果',5) # 如果不想先实例化,并且这个方法适用这个类中所有的情况,那么需要用到classmethod
    # print(a.price)
    # a.change_discount(0.5)
    # print(a.price)
    # 当这个方法的操作只设计静态属性的时候,就应该使用classmethod来装饰这个方法
    
    # step2
    # java
    # class Login:
    #     def __init__(self,name,password):
    #         self.name = name
    #         self.password = password
    #
    #     def login(self):pass
    #
    #     @staticmethod # 伪装成一个静态方法,这样这个方法和这个类和属性都没什么关系,不需要传默认的self
    #     def get_usr_pwd():
    #         usr = input('密码:')
    #         pwd = input('账号:')
    #         Login(usr,pwd)
    
    
    # Login.get_usr_pwd() # 这样就可以直接调用这个方法了,且调用之前不需要实例化任何对象
    # 在完全面向对象的程序中,如果一个函数类还有对象都没关系,那么就用staticmethod将这个函数变成一个静态方法
    

    反射,getattr方法

    知识点整理:

    # 有一个字符串格式的名字存在命名空间里面,可以通过getattr拿到这个字符串的值
    # 形式有类.属性、实例.方法
    # hasattr和getattr是配套使用的,先判断有没有,没有也不报错,如果没有,没有就报错
    # step1
    # class Teacher:
    #     dic = {'查看学生信息':'show_student','查看讲师信息':'show_teacher'}
    #     def show_student(self):
    #         print('show_student')
    # 
    #     def show_teacher(self):
    #         print('show_teacher')
    # 
    #     @classmethod
    #     def func(cls):
    #         print('hahaha')
    
    # hasattr, getattr, delattr
    # ret = getattr(Teacher,'dic') # 字符串类型的数据类型,Teacher.dic,类.属性
    # print(ret)
    # 有一个字符串格式的名字存在命名空间里面,可以通过getattr拿到这个字符串的值
    
    # ret1 = getattr(Teacher,'func')      # 类.方法
    # print(ret1)   #  方法名,方法的内存地址
    # ret1()        # 函数的内存地址加括号,就执行该方法
    
    # if hasattr(Teacher,'dic1'):     # getattr是配套使用的,先判断有没有,没有也不报错,如果没有hasattr,没有就报错
    #     ret = getattr(Teacher,'dic1')
    #
    # aa = Teacher()
    # a_func = getattr(aa, 'show_teacher') # 这样拿到的是函数的内存地址
    # a_func()
    
    # alex = Teacher()
    # for k in Teacher.dic:
    #     print(k)
    # 
    # key = input('输入需求:')
    # if hasattr(alex, Teacher.dic[key]):
    #     func = getattr(alex, Teacher.dic[key])
    #     func()
    

      皑皑

    实现计算机作业:

    import re
    
    # step2 提取括号里面没有其他括号的表达式
    # findall 会找出来所有符合条件的,但是对于3*5*6 + 2*3,匹配乘法的化,上面这种情况会出现漏
    def dealwith(express):
        '''
        将表达式中的符号替换,+- 替换为-,-,-替换为+
        :return:
        '''
        express = express.replace('+-','-')
        express = express.replace('--','+')
        return express
    
    def cal_express_son(exp_son):
        '''
        只用来计算最小型的两个数的乘除法
        :return:
        '''
        if '/' in exp_son:
            a,b = exp_son.split('/')
            return str(float(a) / float(b))
        elif '*' in exp_son:
            a,b  = exp_son.split('*')
            return str(float(a)* float(b))
    
    
    def cal_express_no_bracket(exp):
        '''
        计算没有括号的表达式
        exp:没有经过处理的最内层带括号的表达式
        :return:
        '''
        exp = exp.strip('()')
        # print(exp)
        # 先乘除后加减,找第一个出现的乘法或除法
        while 1:
            ret = re.search('d+.?d*[*/]-?d+.?d*',exp)
            if ret:  # 说明表达式中还有乘除法
                exp_son =  ret.group()  # 子表达式,最简单的乘除法
                print(exp_son)
                ret = cal_express_son(exp_son)
                exp =  exp.replace(exp_son,ret)
                exp = dealwith(exp)
            else:  # 说明表达式中没有乘除了
                ret = re.findall('-?d+.d*',exp)
                # print('***',ret)
                sum = 0
                for i in ret:
                    sum += float(i)
                return str(sum)
    
    def remove_bracket(new_express):
        while 1:
            ret = re.search('([^()]+)',new_express)
            if ret:
                express_no_bracket = ret.group() # 表达式没括号
                print('匹配到内部不在有括号的值',express_no_bracket)
                ret = cal_express_no_bracket(express_no_bracket)
                # print(new_express,express_no_bracket,ret)
                new_express = new_express.replace(express_no_bracket,ret)
                new_express = dealwith(new_express)
                print(new_express)
            else:
                print('表达式中已经没有括号了:',new_express)
                ret = cal_express_no_bracket(new_express)
                # print(ret)
                return ret
                break
    
    express = '1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
    # step1 去空格
    new_express = express.replace('  ','')
    res = remove_bracket(new_express)
    print(res)
    

      

  • 相关阅读:
    insert 和 if x is not None
    python3和Python2的区别(被坑太久了)
    python面试题大全
    Python里的拷贝=====》很容易错误的
    Python中函数参数传递问题
    重回:类,对象,方法,属性
    30 个 Python 语言的特点技巧
    centos7下使用yum安装mysql
    phpinfo.php
    添加开机启动项命令
  • 原文地址:https://www.cnblogs.com/zheng1076/p/11097551.html
Copyright © 2011-2022 走看看