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)