Python 类 以及self.方法、cls.方法与sta.方法的区别

本文深入解析Python中的实例方法、类方法和静态方法,探讨它们的定义、调用方式及访问权限,帮助读者理解不同方法的特点和适用场景。

Python类中的各种方法是通过方法的名字调用的函数,通过定义类和对象,将类和对象当做参数传入方法中,进而获得返回值

Python类中的方法是对象与函数的结合体

以下是python类中对对象的初始化函数以及三种方法的定义

class Test(object):
    def __init__(self, title):  #可定义多个参数
        self.title = title
    def get_title(self):   #定义了实例方法
        return self.title
    @classmethod
    def get_time(cls):  #定义了类方法
        print("On July 2")
    @staticmethod
    def get_grade():      #定义了静态方法
        print("89")
在定义一个类的对象时,需要用到 __init__,self为默认命名的参数(可以为其他的字符串)实际为对象的地址,可以理解为保险箱中存放着很多东西,self为保险箱的编号,可以方便的找到自己的保险箱

 

instance method(需要添加参数“self”)

实例方法的两种调用格式

MS.get_title();  #通过实例调用
Test.get_title(MS)  #通过类的方式调用
In [11]: MS = Test('Molecular system examination')
 
In [12]: MS.get_title()
Out[12]: 'Molecular system examination'
当我们调用方法get_title时,get_title方法实际是将调用的实例对象MS作为参数self传递了进去,self是参数的名称,不是关键字

总结:1、instance method 就是实例对象与函数的结合。

2、使用类调用,第一个参数明确的传递过去一个实例。

 
 
3、使用实例调用,调用的实例被作为第一个参数被隐含的传递过去。
 
 

class method (参数需要添加“cls”)

类方法将类本身当做对象进行操作,在定义类方法时使用@classmethod装饰器定义,其第一个参数是类,约定写为cls。类对象和实例对象都可以调用类方法。

class Test(object):
    time = “On June 2”
    @classmethod
    def get_time(cls):  #定义了类方法
        return cls.time
test_time 是绑定在Test的方法,可以通过类来访问(通过类的实例对象也可以访问,但是传递过去的cls依旧是类)

调用该类函数 :

Test.get_time()
“On June 2”
Human().get_time()
“On June 2”
从上述结果可以看出通过类和类的实例对象均可以访问类方法,但是传递过去的参数,类和实例对象是什么呢?


 
class Test(object):
    time = “On June 2”
    @classmethod
    def get_time(cls):  #定义了类方法
        print (cls)
Test.get_time()
<class '__main__.Test'> 
Test().get_time()
<class '__main__.Test'>
可以看到传递过去的参数均为Test类,无论所访问的是类还是类的实例对象,所传入的cls参数均为类,cls为函数参数,调用时被隐含的传递进去。

总结:1、classmethod 是类对象与函数的结合。

2、可以使用和类的实例调用,但是都是将类作为隐含参数传递过去。

 
 
3、使用类来调用 classmethod 可以避免将类实例化的开销。
 

staticmethod

静态方法是一种普通函数,不会对任何类或者对象进行操作。类对象和实例都可以调用静态方法, 

使用装饰器@staticmethod定义静态方法。

class Test(object):
    @staticmethod
    def add(a,b):  #定义了静态方法
        return a + b
    
Test.add
<function __main__.add>
 
Test().add
<function __main__.add>
 
Test.add(1,2)
3
 
Test().add(1,2)
3
可以从上述代码中发现,在类和实例中调用add静态方法时,方法均是一个普通的函数,没有绑定任何一个特定的类或者实例,可以使用类或者类的实例调用,并且没有任何隐含参数的传入。

 

总结:1、当一个函数逻辑上属于一个类又不依赖与类的属性的时候,可以使用staticmethod。

 
2、使用 staticmethod 可以避免每次使用的时都会创建一个对象的开销。
3、staticmethod 可以使用类和类的实例调用。但是不依赖于类和类的实例的状态。
 
 

对三种方法的归纳总结:

 

方法    调用情况    访问权限
普通方法    可以通过实例来调用    可访问实例属性,无法访问类属性
类方法    可以通过类名和实例来调用    可访问类属性,无法访问实例属性
静态方法    可以通过类名和实例来调用    无法访问类属性及实例属性(仅可通过传值的方式)
 

参考资料

 

https://www.zhihu.com/question/22869546/answer/22933397
--------------------- 
作者:Z_shoushow 
来源:优快云 
原文:https://blog.youkuaiyun.com/Z_shoushow/article/details/80363330 
版权声明:本文为博主原创文章,转载请附上博文链接!

D:\pycharm\web\.venv\Scripts\python.exe "D:/pycharm/PyCharm Community Edition 2024.3/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --path D:\pycharm\web\scripts\imp\test_IHML.py Testing started at 17:17 ... Launching pytest with arguments D:\pycharm\web\scripts\imp\test_IHML.py --no-header --no-summary -q in D:\pycharm\web\scripts\imp ============================= test session starts ============================= collecting ... collected 3 items test_IHML.py::Test_imp::test01_login test_IHML.py::Test_imp::test02_pubash test_IHML.py::Test_imp::test03_home ============================== 3 failed in 8.32s ============================== FAILED scripts\imp\test_IHML.py:18 (Test_imp.test01_login) self = <scripts.imp.test_IHML.Test_imp object at 0x000001F24352FF90> def test01_login(self): # 进行登录 > self.login_sta.log_start("13800000002", "929itheima.CN032@.20250313") test_IHML.py:21: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ..\..\page\imp\login_page.py:54: in log_start self.login_imp.imp_moble(moble) ..\..\page\imp\login_page.py:36: in imp_moble self.imp_sta(self.login.get_moble(), moble) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <page.imp.login_page.login object at 0x000001F244140090> def get_moble(self): # 使用账号元素封装输入方法 > return self.get_element(self.moble) E TypeError: base_imp.get_element() missing 1 required positional argument: 'location' ..\..\page\imp\login_page.py:19: TypeError FAILED scripts\imp\test_IHML.py:26 (Test_imp.test02_pubash) self = <scripts.imp.test_IHML.Test_imp object at 0x000001F24413A3D0> def test02_pubash(self): > self.pubash_sta.start_pubash("11", "11") test_IHML.py:28: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ..\..\page\imp\pubash_page.py:98: in start_pubash self.pubash_imp.imp_hepay() ..\..\page\imp\pubash_page.py:60: in imp_hepay s
03-14
import os import win32gui import win32con import win32api import logging import pythoncom import time import unittest import tempfile import shutil import win32com.client from win32com.client import DispatchEx from PIL import ImageGrab import task_handler # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(), logging.FileHandler("office_test.log") ] ) # 创建临时文档目录 TEST_DIR = tempfile.mkdtemp(prefix="office_test_") logging.info(f"测试目录: {TEST_DIR}") # 指定要测试的文档路径 WORD_FILE = r"D:\GitProjects\T社量産_第八弾\Input\250721(From DN)\before\MET-G_SETTING-CSTD-0-XX-X-C7-429D-a.docx" # 替换为实际的Word文档路径 EXCEL_FILE = r"D:\GitProjects\T社量産_第八弾\Input\250721(From DN)\before\MET-B_SEAREM-CSTD-1-XX-X-C6-613D-B.xlsx" # 替换为实际的Excel文档路径 # 截图工具 def capture_window(hwnd, filename): """捕获指定窗口的截图""" try: # 获取窗口位置 left, top, right, bottom = win32gui.GetWindowRect(hwnd) width = right - left height = bottom - top # 截图 img = ImageGrab.grab(bbox=(left, top, right, bottom)) img.save(filename) logging.info(f"截图保存到: {filename}") return True except Exception as e: logging.error(f"截图失败: {e}") return False class OfficeLocatorTest(unittest.TestCase): office_instances = [] @classmethod def setUpClass(cls): """初始化测试环境""" logging.info("=== 准备测试环境 ===") # 验证文件存在 if not os.path.exists(WORD_FILE): logging.error(f"指定的Word文件不存在: {WORD_FILE}") raise FileNotFoundError(f"指定的Word文件不存在: {WORD_FILE}") if not os.path.exists(EXCEL_FILE): logging.error(f"指定的Excel文件不存在: {EXCEL_FILE}") raise FileNotFoundError(f"指定的Excel文件不存在: {EXCEL_FILE}") logging.info(f"使用的Word文档: {WORD_FILE}") logging.info(f"使用的Excel文档: {EXCEL_FILE}") # 初始化COM pythoncom.CoInitialize() @classmethod def tearDownClass(cls): """清理测试环境""" logging.info("=== 清理测试环境 ===") # 关闭所有Office实例 while cls.office_instances: instance = cls.office_instances.pop() task_handler.close_pre_instance(instance) # 清理临时目录 try: shutil.rmtree(TEST_DIR) logging.info(f"已删除临时目录: {TEST_DIR}") except Exception as e: logging.error(f"删除临时目录失败: {e}") # 卸载COM pythoncom.CoUninitialize() def setUp(self): """每个测试前的准备工作""" logging.info(f"\n=== 开始测试: {self._testMethodName} ===") self.start_time = time.time() def tearDown(self): """每个测试后的清理工作""" duration = time.time() - self.start_time logging.info(f"测试完成: {self._testMethodName}, 耗时: {duration:.2f}秒") # 关闭打开的文档 for app, filename in self.office_instances.copy(): try: task_handler.close_pre_instance((app, filename)) self.office_instances.remove((app, filename)) except Exception as e: logging.error(f"关闭文档失败: {e}") def test_open_close_documents(self): """测试打开和关闭文档功能""" # 打开Word文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.assertIsNotNone(word_app) self.assertTrue(os.path.exists(word_file)) self.office_instances.append((word_app, word_file)) # 打开Excel文档 excel_app, excel_file = task_handler.open_excel_document_ex(EXCEL_FILE) self.assertIsNotNone(excel_app) self.assertTrue(os.path.exists(excel_file)) self.office_instances.append((excel_app, excel_file)) # 验证窗口存在 hwnd_word = task_handler.find_window(os.path.basename(word_file)) self.assertNotEqual(hwnd_word, 0) hwnd_excel = task_handler.find_window(os.path.basename(excel_file)) self.assertNotEqual(hwnd_excel, 0) # 关闭文档 task_handler.close_pre_instance((word_app, word_file)) self.office_instances.remove((word_app, word_file)) task_handler.close_pre_instance((excel_app, excel_file)) self.office_instances.remove((excel_app, excel_file)) # 验证窗口关闭 win32gui.PumpWaitingMessages() time.sleep(1) hwnd_word = task_handler.find_window(os.path.basename(word_file)) self.assertEqual(hwnd_word, 0) hwnd_excel = task_handler.find_window(os.path.basename(excel_file)) self.assertEqual(hwnd_excel, 0) def test_window_positioning(self): """测试窗口定位功能""" # 打开文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) excel_app, excel_file = task_handler.open_excel_document_ex(EXCEL_FILE) self.office_instances.extend([(word_app, word_file), (excel_app, excel_file)]) # 获取窗口句柄 hwnd_word = task_handler.find_window(os.path.basename(word_file)) hwnd_excel = task_handler.find_window(os.path.basename(excel_file)) # 定位窗口 task_handler.diff_office_ui_layout([(word_app, word_file), (excel_app, excel_file)]) # 验证位置 rect_word = win32gui.GetWindowRect(hwnd_word) rect_excel = win32gui.GetWindowRect(hwnd_excel) # 添加调试信息 logging.info(f"Word窗口位置: {rect_word}") logging.info(f"Excel窗口位置: {rect_excel}") logging.info(f"Word右边界: {rect_word[2]} | Excel左边界: {rect_excel[0]}") # 验证Word窗口在左侧 self.assertLess(rect_word[0], rect_excel[0], "Word窗口不在Excel左侧") # 验证Excel窗口在右侧(允许相邻边界) self.assertGreaterEqual(rect_excel[0], rect_word[2], "Excel窗口未在Word右侧或相邻") # 验证无重叠(确保Excel左边界不在Word内部) self.assertLessEqual(rect_excel[0], rect_word[2] + 1, # 允许1像素容差 "窗口存在重叠") # 截图 capture_window(hwnd_word, os.path.join(TEST_DIR, "word_position.png")) capture_window(hwnd_excel, os.path.join(TEST_DIR, "excel_position.png")) def test_text_paragraph_locating(self): """测试文本段落定位功能""" # 打开Word文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.office_instances.append((word_app, word_file)) # 获取文档对象 doc = word_app.ActiveDocument # 测试定位第二段落 # 注意:这里的索引需要根据实际文档内容调整 task_handler.add_mark_for_word_paras(word_app, doc, 1) # 验证标记存在 mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "段落标记未找到") # 截图验证 hwnd = task_handler.find_window(os.path.basename(word_file)) capture_window(hwnd, os.path.join(TEST_DIR, "paragraph_mark.png")) def test_table_locating(self): """测试表格定位功能""" # 打开Word文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.office_instances.append((word_app, word_file)) # 获取文档对象 doc = word_app.ActiveDocument # 定位第一个表格 # 注意:这里的索引需要根据实际文档内容调整 task_handler.add_mark_for_word_tables(word_app, doc, 0) # 验证标记存在 mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "表格标记未找到") # 截图验证 hwnd = task_handler.find_window(os.path.basename(word_file)) capture_window(hwnd, os.path.join(TEST_DIR, "table_mark.png")) def test_picture_locating(self): """测试图片定位功能""" # 打开Word文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.office_instances.append((word_app, word_file)) # 获取文档对象 doc = word_app.ActiveDocument # 定位第一张图片 # 注意:这里的索引需要根据实际文档内容调整 task_handler.add_mark_for_word_picture(word_app, doc, 0) # 验证标记存在 mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "图片标记未找到") # 截图验证 hwnd = task_handler.find_window(os.path.basename(word_file)) capture_window(hwnd, os.path.join(TEST_DIR, "picture_mark.png")) def test_excel_cell_locating(self): """测试Excel单元格定位功能""" # 打开Excel文档 excel_app, excel_file = task_handler.open_excel_document_ex(EXCEL_FILE) self.office_instances.append((excel_app, excel_file)) # 获取工作簿和工作表 wb = excel_app.ActiveWorkbook ws = wb.ActiveSheet # 定位单元格B4 (根据实际文档内容调整) cell = ws.Range("B4") task_handler.add_mark(ws, cell) # 验证标记存在 mark_found = False for shape in ws.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "Excel单元格标记未找到") # 截图验证 hwnd = task_handler.find_window(os.path.basename(excel_file)) capture_window(hwnd, os.path.join(TEST_DIR, "excel_cell_mark.png")) def test_clear_marks(self): """测试清除标记功能""" # 打开Word文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.office_instances.append((word_app, word_file)) # 添加段落标记 doc = word_app.ActiveDocument task_handler.add_mark_for_word_paras(word_app, doc, 1) # 清除标记 task_handler.clear_word_mark(doc) # 验证标记已清除 mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertFalse(mark_found, "段落标记未清除") def test_office_location_api(self): """测试office_location API""" # 打开文档 word_app, word_file = task_handler.open_word_document_ex(WORD_FILE) self.office_instances.append((word_app, word_file)) # 定位段落 data = { "filename": word_file, "data_index": 1, "data_type": "text" } task_handler.office_location(data, self.office_instances) # 验证标记存在 doc = word_app.ActiveDocument mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "通过API添加段落标记失败") # 清除标记 task_handler.clear_word_mark(doc) # 定位表格 data = { "filename": word_file, "data_index": 0, "data_type": "table" } task_handler.office_location(data, self.office_instances) # 验证标记存在 mark_found = False for shape in doc.Shapes: if shape.Name == "lauf_mark": mark_found = True break self.assertTrue(mark_found, "通过API添加表格标记失败") if __name__ == "__main__": # 运行测试 unittest.main(exit=False) # 显示测试结果 logging.info("=== 所有测试完成 ===") logging.info(f"测试截图保存在: {TEST_DIR}") logging.info("请查看office_test.log获取详细测试日志") # 防止立即退出(可选) input("按Enter键退出...") 会不会是测试代码有问题,因为之前测试过,是能正常打开的,handle里面只有一个窗口查找函数,word和excel是在一起的
最新发布
09-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值