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)

浙公网安备 33010602011771号