最近在学习类的一些知识,类顾名思义就是将一大堆函数进行封装,将其整理供外部调用,而在类中函数进行调用的过程中需要实例化对象,就是像这种操作:
def __init__(self):
self.abc = abc
你后续所有有关于这个实例对象的变量都需要写一遍这个。在你封装几个函数过程中,可能会出现需要修改的变量过多,短时间无从下手,后面我发现有个装饰器@staticmethod,这个装饰器在每个类方法上面调用后,可以将函数定义为静态方法,可以直接在类中调用而不需要实例化对象。我就我最近写的一个计算器函数进行解析,其中包括了计算器的一些实现过程的分析,在这里记录一下。
计算器主要是想像eval()函数一样处理简单的算式,下面是我计算器的简单实现的一个构思:
1、创建一个计算容器包含加减乘除幂求余;
2、利用正则化方法提取字符串中的数字于符号形成一个列表;
3、建立计算优先级,幂 > 乘、除、取余 > 加、减;
4、通过递归计算出算式答案;
这里用到了两个python相关的库
import operator
import re
首先是计算的容器:
# 二元操作符映射表
operators = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'%': operator.mod,
'**': operator.pow
}
然后是利用正则方法re.findall找到字符串中的数字于运算符。特别的:求幂的“**”这种运算符在使用转义字符划分时不能单独列出来,所以要使用[]先将普通运算符提出来再加上转义字符于求幂的第二个“*”即:
tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)
这个代码会将我们的字符串转换成一个列表 [‘a’, ‘+’, ‘b’] ,接下来就对目标列表进行判断,计算前提判断运算顺序
(幂 > 乘、除、取余 > 加、减):
def find_operator(tokens):
priority1_ops = ['**']
priority2_ops = ['*', '/', '%']
priority3_ops = ['+', '-']
for i in range(len(tokens)):
if tokens[i] in priority1_ops:
return i
for i in range(len(tokens)):
if tokens[i] in priority2_ops:
return i
for i in range(len(tokens)):
if tokens[i] in priority3_ops:
return i
raise ValueError("无效的表达式")
最后就是运算步骤,通过递归计算到最后一个数停止进行:
def calculate_expression(tokens):
if len(tokens) == 1:
# 已经到达最底层,返回结果
return float(tokens[0])
elif len(tokens) == 3:
# 处理简单的表达式
op, num1, num2 = tokens
return operators[op](float(num1), float(num2))
else:
# 处理复合表达式
op_idx = find_operator(tokens)
op = tokens[op_idx]
num1 = tokens[op_idx-1]
num2 = tokens[op_idx+1]
result = operators[op](float(num1), float(num2))
# 递归计算剩余的表达式
tokens[op_idx-1:op_idx+2] = [str(result)]
return calculate_expression(tokens)
直接输入我们需要进行运算的字符串式子:result = evaluate_expression(‘5+12/2+2*3-11%3+3**3’)
可以得到:result = 42.0
我们下面将这写方法封装成类,因为有方法中有很多变量需要调用,比如计算容器,以及优先级符号等。所以要对这些进行变量实例化创建,在__init__函数中:
class PrimaryCalculatorV2:
operators = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'%': operator.mod,
'**': operator.pow
}
priority1_ops = ['**']
priority2_ops = ['*', '/', '%']
priority3_ops = ['+', '-']
def __init__(self):
self.operators = PrimaryCalculatorV2.operators
self.priority1_ops = PrimaryCalculatorV2.priority1_ops
self.priority2_ops = PrimaryCalculatorV2.priority2_ops
self.priority3_ops = PrimaryCalculatorV2.priority3_ops
def find_operator(self, tokens):
for i in range(len(tokens)):
if tokens[i] in self.priority1_ops:
return i
for i in range(len(tokens)):
if tokens[i] in self.priority2_ops:
return i
for i in range(len(tokens)):
if tokens[i] in self.priority3_ops:
return i
raise ValueError("无效的表达式")
def calculate_expression(self, tokens):
if len(tokens) == 1:
return tokens[0] if tokens[0].isdigit() else float(tokens[0])
elif len(tokens) == 3:
num1, op, num2 = tokens
return self.operators[op](float(num1), float(num2))
else:
op_idx = self.find_operator(tokens)
op = tokens[op_idx]
num1 = tokens[op_idx - 1]
num2 = tokens[op_idx + 1]
result = self.operators[op](float(num1), float(num2))
tokens[op_idx - 1:op_idx + 2] = [str(result)]
return self.calculate_expression(tokens)
def evaluate_expression(self, expression):
tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)
result = self.calculate_expression(tokens)
return result
而我们如果使用装饰器@staticmethod,将我们的方法申明为静态的,我们就可以不在__init__中进行实例化变量创建了,少写了几行代码,不过注意的是,在类中调用的有关容器于运算优先级变量的过程中,需要直接调用我们的类名。静态写法如下:
class PrimaryCalculatorV1:
operators = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'%': operator.mod,
'**': operator.pow
}
priority1_ops = ['**']
priority2_ops = ['*', '/', '%']
priority3_ops = ['+', '-']
def __init__(self):
pass
@staticmethod
def __find_operator(tokens):
for i in range(len(tokens)):
if tokens[i] in PrimaryCalculatorV1.priority1_ops:
return i
for i in range(len(tokens)):
if tokens[i] in PrimaryCalculatorV1.priority2_ops:
return i
for i in range(len(tokens)):
if tokens[i] in PrimaryCalculatorV1.priority3_ops:
return i
raise ValueError("无效的表达式")
@staticmethod
def __calculate_expression(tokens):
if len(tokens) == 1:
return tokens[0] if tokens[0].isdigit() else float(tokens[0])
elif len(tokens) == 3:
num1, op, num2 = tokens
return PrimaryCalculatorV1.operators[op](float(num1), float(num2))
else:
op_idx = PrimaryCalculatorV1.__find_operator(tokens)
op = tokens[op_idx]
num1 = tokens[op_idx - 1]
num2 = tokens[op_idx + 1]
result = PrimaryCalculatorV1.operators[op](float(num1), float(num2))
tokens[op_idx - 1:op_idx + 2] = [str(result)]
return PrimaryCalculatorV1.__calculate_expression(tokens)
def evaluate_expression(self, expression):
tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)
result = self.__calculate_expression(tokens)
return result
以上就是本菜鸟所掌握的一些类有关知识了,如果有错误还有问题点,或者代码有问题的地方,欢迎各位大佬提出讨论,非常感谢🤣🤣🤣🤣🤣