反射getattr

本文介绍了Python中类属性操作和反射机制。@property可将类方法伪装成属性,还有相关的setter和deleter装饰器。还介绍了类方法、静态方法及其应用场景。反射机制包括getattr、hasattr、setattr和delattr,可用于获取、判断、设置和删除属性,有多种应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@property   将类中的方法伪装成属性

与@property相关的俩个   @方法.setter   修改操作    @方法.deleter   删除一个property属性的时候会执行被deleter装饰的方法

 在类的命名空间有什么:

  静态属性,

  方法(动态属性),

  @property方法

  类方法(@classmethod)

    类方法的默认参数:cls,指的是调用这个方法的类名

    类方法的调用方式:通过类名.类方法调用,本质就是方法  

    应用场景:如果你的整个方法中都没有用到对象命名空间中的名字,且你用到了类的命名空间中的名字(普通方法和property方法除外)

  静态方法(@staticmethod,)

    这个函数不需要默认参数self,cls

    静态方法的调用方式:通过类名.方法调用,本质是函数

    应用场景:函数在类中定义的时候,即类中函数

isinstance:判断对象与类直接的关系

  判断这个对象是不是类的对象,这个类子类的对象

issubclass(a,b):判断类与类之间的关系,(ab都必须是类,否则报错)

  判断这个类a是不是另一个类b的子类

反射 getattr  

  使用:getattr(变量名(命名空间),字符串(属于一个命名空间的变量名))

  定义:反射 指使用字符串数据类型的变量名来获取这个变量的值

  应用场景:

    input:用户输入

    文件:从文件中读出的字符串,想转换成变量的名字

    网络:将网络传输的字符串转换成年糕变量的名字

反射类的变量:静态属性,类方法,静态方法

class Foo:
    School = "oldboy"
    County = "China"
    Language = "Chiness"
    @classmethod
    def class_method(cls):
        print(cls.School)
    def name(self):
        print("alex")
a = Foo()
while True:
    ch = input(">>>>>>>>>:").strip()
    if hasattr(a,ch):       #has 判断对象中是否存在这个方法
        getattr(a,ch)()     #执行方法

反射对象中的变量:对象属性,普通方法

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eating(self):
        print("%s is eating"%self.name)
a = Foo("lin",23)
if hasattr(a,"name"):
    print(getattr(a, "name"))   #lin is eating
getattr(a,"eating")()   #lin is eating

反射文本中的变量 

import sys

sys.modules[__name__]    #反射本文件中的变量,固定使用这个命名空间

import sys  #加载sys模块
a = 1
b = 2
name ="alex"
def hello():
    print("hello word")
print(getattr(sys.modules[__name__], "a"))
getattr(sys.modules[__name__],"hello")()

hasattr   (a,"b") 判断对象中有没有“b”这个方法,与getattr配合使用,防止报错

setattr (a,"b",c) 接受三个参数,命名空间,“变量名”,变量值

  

class Foo:
    Country = "China"
def func():
    print("hello world")
Foo.Shool = "old boy"
setattr(Foo,"teacher","alex")   #Foo.Shool = "old boy"与他作用相同,都是给类中增加属性
print(Foo.__dict__) # 'Country': 'China','Shool': 'old boy', 'teacher': 'alex'等

delattr   (a,"b")   删除命名空间中b这个属性,如果没有会报错

class Foo:
    Country = "China"
def func():
    print("hello world")
Foo.Shool = "old boy"
del Foo.Country
print(Foo.__dict__)
delattr(Foo,'Country')      #del Foo.Country作用是一样的
print(Foo.__dict__)

 

转载于:https://www.cnblogs.com/yuncong/p/9568146.html

test_api.py: import pytest from unit_tools.apiutils_single import RequestsBase from common.yaml_util import YamlUtil class TestLogin: """登录模块""" @pytest.mark.parametrize('api_info,testcase', YamlUtil().read_def_yaml('get_new.yaml')) def test_login_module(self, api_info, testcase): api_info = YamlUtil().read_def_yaml('get_new.yaml')[0] RequestsBase().execute_test_cases(api_info,testcase) apiutils_single.py: import json import re from idlelib.rpc import response_queue from importlib.metadata import files import jsonpath from common.yaml_util import YamlUtil from unit_tools.debugtalk import DebugTalk from common.requests_util import SendRequests from unit_tools.assertion_utils import Assertions class RequestsBase: def __init__(self): self.send_request = SendRequests() self.asserts = Assertions() def parse_and_replace_variables(self, yml_data): """ 解析并替换YAML数据中的变量引用,如:${get_extract_data(token)} :param yml_data: 解析的YAML数据 :return: 返回的是dict类型 """ yml_data_str = yml_data if isinstance(yml_data, str) else json.dumps(yml_data, ensure_ascii=False) for _ in range(yml_data_str.count('${')): if '${' in yml_data_str and '}' in yml_data_str: start_index = yml_data_str.index('$') end_index = yml_data_str.index('}', start_index) variable_data = yml_data_str[start_index:end_index + 1] # 使用正则表达式提取函数名和参数 match = re.match(r'\$\{(\w+)\((.*?)\)\}', variable_data) if match: func_name, func_params = match.groups() func_params = func_params.split(',') if func_params else [] # 使用面向对象反射getattr调用函数 extract_data = getattr(DebugTalk(), func_name)(*func_params) # 使用正则表达式替换原始字符中的变量引用为调用后的结果 yml_data_str = re.sub(re.escape(variable_data), str(extract_data), yml_data_str) # 还原数据,将其转换为字典类型 try: data = json.loads(yml_data_str) except json.JSONDecodeError: data = yml_data_str return data def execute_test_cases(self, api_info,testcase): """ 规范yaml接口信息,执行接口、提取结果以及断言操作 :param base_info: (dict)yaml里面接口基本信息 :param testcase: (dict)yaml里面接口测试用例信息 :return: """ try: url = api_info['url'] api_name = api_info['api_name'] method = api_info['method'] headers = api_info.get('headers', None) if headers is not None: headers = eval(self.parse_and_replace_variables(headers)) if isinstance(headers, str) else headers cookies = api_info.get('cookies', None) if cookies is not None: cookies = eval(self.parse_and_replace_variables(cookies)) if isinstance(cookies, str) else cookies # 处理testCase下面的数据 #for testcase in api_info['TestCase']: case_name = testcase.pop('case_name') # 通过变量引用处理断言结果 val_result = self.parse_and_replace_variables(testcase.get('validation')) testcase['validation'] = val_result validation = testcase.pop('validation') # 处理接口返回值提取部分 extract, extract_list = testcase.pop('extract', None), testcase.pop('extract_list', None) # 处理参数类型和请求参数 for param_type, param_value in testcase.items(): if param_type in ['params', 'data', 'json']: request_params = self.parse_and_replace_variables(param_value) testcase[param_type] = request_params files = None response = self.send_request.execute_api_request( api_name=api_name, url=url, method=method, headers=headers, case_name=case_name, cookies=cookies, files=files, **testcase ) status_code, response_text = response.status_code, response.text print(response.text) #接口返回值提取 if extract is not None: self.extract_data(extract, response_text) if extract_list is not None: self.extract_data_list(extract_list,response_text) #处理接口断言 self.asserts.assert_result(validation,response.json(),status_code) except Exception as e: print(f'出现异常,--{e}') @classmethod def extract_data(cls, testcase_extract, response_text): """ 提取单个参数,提取接口的返回参数,支持正则表达式提取和json提取器 :param testcase_extract: (dict)yaml文件中的extract值,例如:{'token': '$.token'} :param response_text: (str)接口的实际返回值 :return: """ extract_data = None try: for key, value in testcase_extract.items(): if any(pat in value for pat in ['(.*?)', '(.+?)', r'(\d+)', r'(\d*)']): ext_list = re.search(value, response_text) extract_data = {key: int(ext_list.group(1)) if r'(\d+)' in value else ext_list.group(1)} elif "$" in value: extract_json = jsonpath.jsonpath(json.loads(response_text), value) extract_data = {key: extract_json} if extract_json else { key: "未提取到数据,请检查接口返回信息或表达式!"} if extract_data: YamlUtil().write_yaml(extract_data) except re.error: print('正则表达式解析错误,请检查yaml文件extract表达式是否正确!') except json.JSONDecodeError: print('JSON解析错误,请检查yaml文件extract表达式是否正确!') @classmethod def extract_data_list(cls, testcase_extract_list, response_text): """ 提取多个参数,提取接口的返回参数,支持正则表达式提取和json提取器 :param testcase_extract_list: (dict)yaml文件中的extract_list值,例如:{'token': '$.token'} :param response_text: (str)接口的实际返回值 :return: """ extract_data = None try: for key, value in testcase_extract_list.items(): if any(pat in value for pat in ['(.*?)', '(.+?)', r'(\d+)', r'(\d*)']): ext_list = re.findall(value, response_text, re.S) if ext_list: extract_data = {key: ext_list} elif "$" in value: extract_json = jsonpath.jsonpath(json.loads(response_text), value) if extract_json: extract_data = {key: extract_json} else: extract_data = {key: "未提取到数据,请检查接口返回信息或表达式!"} if extract_data: YamlUtil().write_yaml(extract_data) except re.error: print('正则表达式解析错误,请检查yaml文件extract表达式是否正确!') except json.JSONDecodeError: print('JSON解析错误,请检查yaml文件extract表达式是否正确!') if __name__ == '__main__': api_yaml_data = YamlUtil().read_def_yaml('get_new.yaml') print(api_yaml_data) req = RequestsBase() req.execute_test_cases(api_yaml_data[0][0],api_yaml_data[0][1]) 为什么只运行apiutils_single.py就正常运行,运行test_api.py就报错:出现异常,--list indices must be integers or slices, not str
最新发布
05-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值