self与static、get_class()与get_called_class()区别

本文解析了PHP中self、static关键字的区别,以及get_class和get_called_class的作用,通过实例演示了它们在类和实例调用时的行为。

在日常项目代码中,大家一定经常能看到self、static、get_class、get_called_class()的使用,但不一定都知道它们的区别,本文就以个人理解来说明一下。

1、self与static

self指向的是当前类,既self代码所在类;static首先指向调用类,既谁调用static所在类的代码就指向谁,一般指向子类。如果没有子类,则与self相同指向的是当前类;

示例:

<?php
 
class Father{
    protected  static $name = "father";
    public static function whoami_self(){
        echo self::$name."\n";
    }
     
    public static function whoami_static(){
        echo static::$name."\n";
    }
     
    public static function getInstance_self(){
        return new self();
    }
     
    public static function getInstance_static(){
        return new static();
    }
}
 
class FatherBrother extends Father{
    protected  static $name = "uncle";
}
 
FatherBrother::whoami_self(); //father
FatherBrother::whoami_static(); //uncle
var_dump(FatherBrother::getInstance_self()); //father
var_dump(var_dump(FatherBrother::getInstance_static())); //uncle

2、get_class()与get_called_class()

get_class()指向当前类,get_called_class()指向调用类,与上述self与static类似;

示例:

    class Foo{
      public function test(){
         var_dump(get_class());
      }
 
      public function test2(){
        var_dump(get_called_class());
      }
 
      public static function test3(){
        var_dump(get_class());
      }
 
      public static function test4(){
        var_dump(get_called_class());
      }
   }
 
   class B extends Foo{
 
   }
 
   $B=new B(); 
   $B->test(); //Foo
   $B->test2(); //B
   Foo::test3(); //Foo
   Foo::test4(); //Foo
   B::test3(); //Foo
   B::test4(); //B

from email.mime import application import random import time import sys import psutil from PySide6.QtCore import QThread, Signal, QObject, QMutex class WorkerThread(QThread): log_signal = Signal(str) finished_signal = Signal() def __init__(self, config): super().__init__() self.config = config self.mutex = QMutex() self._running = True self.WAIT_MEDIUM = int(self.config['TimeSettings']['WAIT_MEDIUM']) self.WAIT_LONG = int(self.config['TimeSettings']['WAIT_LONG']) self.WAIT_PERFORMANCE = int(self.config['TimeSettings']['WAIT_PERFORMANCE']) self.BARCODE_ALERT_COUNT = int(self.config['TimeSettings']['BARCODE_ALERT_COUNT']) # 延迟导入的模块引用 self.Application = None self.ElementNotFoundError = None self.find_elements = None self.TimeoutError = None self.wait_until = None self.ElementNotEnabled = None def import_pywinauto(self): """安全地导入pywinauto模块""" try: # 动态导入pywinauto相关模块 import pywinauto from pywinauto import Application as App from pywinauto.findwindows import ElementNotFoundError as ENFError from pywinauto.findwindows import find_elements as fe from pywinauto.timings import TimeoutError as TError from pywinauto.timings import wait_until as wu from pywinauto.base_wrapper import ElementNotEnabled as ENE # 保存引用 self.Application = App self.ElementNotFoundError = ENFError self.find_elements = fe self.TimeoutError = TError self.wait_until = wu self.ElementNotEnabled = ENE self.log_signal.emit("pywinauto导入成功") return True except ImportError as e: self.log_signal.emit(f"导入pywinauto失败: {e}") return False except Exception as e: self.log_signal.emit(f"导入pywinauto时发生异常: {e}") return False def run(self): # 安全地导入pywinauto if not self.import_pywinauto(): self.log_signal.emit("无法导入pywinauto,功能受限") TARGET_WINDOW_TITLE = "请扫描或输入条码" while self.is_running(): try: # 性能检查 cpu_percent = psutil.cpu_percent(interval=0.1) mem_percent = psutil.virtual_memory().percent if cpu_percent > 80 or mem_percent > 70: time.sleep(1) continue # 查找窗口 windows = self.find_elements(visible_only=True) found_window = None for win in windows: if win.name == TARGET_WINDOW_TITLE: found_window = win break if not found_window: self.log_signal.emit("没有找到窗体") time.sleep(3) continue handle = found_window.handle # 连接窗口 app = self.Application(backend="uia").connect(handle=handle) dialog = app.window(handle=handle) # 使用标签定位两个输入框 edit1, edit2 = self.find_edit_boxes_by_labels(dialog) if not edit1 or not edit2: self.log_signal.emit("无法定位输入框,跳过本次循环") time.sleep(3) continue # 查找确定按钮 confirm_btn = dialog.child_window(title="确定", control_type="Button") # 第一次检查输入框是否为空 val1 = edit1.get_value().strip() val2 = edit2.get_value().strip() if val1 or val2: self.log_signal.emit("检测到条码已录入,跳过填充") time.sleep(3) continue self.log_signal.emit("检测到条码框为空,等待2秒后再次确认") time.sleep(2) # 再次检查窗口是否存在 if not self.is_window_valid(handle): self.log_signal.emit("窗口已关闭,跳过填充") continue # 再次检查输入框是否为空 val1 = edit1.get_value().strip() val2 = edit2.get_value().strip() if val1 or val2: self.log_signal.emit("检测到条码已录入,跳过填充") continue # 开始填充 barcode1 = self.generate_simulated_barcode() barcode2 = self.generate_simulated_barcode() edit1.set_text(barcode1) edit2.set_text(barcode2) # 等待按钮可用 for _ in range(5): if confirm_btn.is_enabled(): break time.sleep(0.5) confirm_btn.click() self.log_signal.emit(f"已自动填充条码: {barcode1}, {barcode2}") time.sleep(0.5) # 给窗口关闭一点时间 except (self.ElementNotFoundError, TimeoutError) as e: self.log_signal.emit(f"查找控件失败: {str(e)}") time.sleep(3) except self.ElementNotEnabled as e: self.log_signal.emit(f"控件不可操作: {str(e)}") time.sleep(1) except Exception as e: self.log_signal.emit(f"发生异常: {str(e)}", exc_info=True) time.sleep(3) self.wait_with_check(3) self.finished_signal.emit() def is_window_valid(self,handle): try: app = self.Application(backend="uia").connect(handle=handle) window = app.window(handle=handle) window.exists() return True except: return False def generate_simulated_barcode(self): prefix = "AUTO_" timestamp = int(time.time()) % 100000 random_part = random.randint(1000, 9999) return f"{prefix}{timestamp}{random_part}" def find_edit_boxes_by_labels(self,dialog): """ 根据 '子板1' 和 '子板2' 的 Static 标签查找对应的 Edit 控件 """ try: # 查找两个 Static 标签 label1 = dialog.child_window(title="子板1", control_type="Text") label2 = dialog.child_window(title="子板2", control_type="Text") if not label1 or not label2: self.log_signal.emit("找不到标签控件,跳过填充") return None, None # 获取下一个兄弟控件(即 Edit 输入框) edit1 = label1.parent().children(control_type="Edit")[0] edit2 = label2.parent().children(control_type="Edit")[1] return edit1, edit2 except Exception as e: self.log_signal.emit(f"通过标签查找输入框失败: {str(e)}") return None, None def stop(self): self.mutex.lock() self._running = False self.mutex.unlock() def is_running(self): self.mutex.lock() running = self._running self.mutex.unlock() return running def wait_with_check(self, seconds): """等待指定的秒数,但每0.1秒检查一次停止标志""" total_msec = seconds * 1000 interval = 100 # 每次等待100ms while total_msec > 0: if not self.is_running(): return False sleep_time = min(interval, total_msec) self.msleep(sleep_time) total_msec -= sleep_time return True class Controller(QObject): log_send = Signal(str) finished = Signal() def __init__(self, config): super().__init__() self.config = config self.worker_thread = None def start(self): if self.worker_thread and self.worker_thread.isRunning(): return self.worker_thread = WorkerThread(self.config) self.worker_thread.log_signal.connect(self.log_send) self.worker_thread.finished_signal.connect(self.on_finished) self.worker_thread.start() def stop(self): if self.worker_thread and self.worker_thread.isRunning(): self.worker_thread.stop() self.worker_thread.quit() if not self.worker_thread.wait(2000): # 等待2秒线程结束 self.worker_thread.terminate() # 如果超时则强制终止 def on_finished(self): self.finished.emit() def ini_controller(self): self.controller = Controller(self.config) self.controller.log_send.connect(self.log_send) self.controller.finished.connect(self.handle_finished) def handle_finished(self): self.logger.info("正在停止程序,线程资源已释放...") self.update_from_ui("等待启动","black") self.update_ui_state('idle') self.flag = 'idle' 点击停止按钮后触发self.controller.stop() self.logger.info("正在停止程序...") 日志只有正在停止程序,没有打印正在停止程序,线程资源已释放...
08-03
class staticmethod(object): """ staticmethod(function) -> method Convert a function to be a static method. A static method does not receive an implicit first argument. To declare a static method, use this idiom: class C: @staticmethod def f(arg1, arg2, ...): ... It can be called either on the class (e.g. C.f()) or on an instance (e.g. C().f()). The instance is ignored except for its class. Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see the classmethod builtin. """ def __get__(self, *args, **kwargs): # real signature unknown """ Return an attribute of instance, which is of type owner. """ pass def __init__(self, function): # real signature unknown; restored from __doc__ pass @staticmethod # known case of __new__ def __new__(*args, **kwargs): # real signature unknown """ Create and return a new object. See help(type) for accurate signature. """ pass __func__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default __isabstractmethod__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default __dict__ = None # (!) real value is "mappingproxy({'__get__': <slot wrapper '__get__' of 'staticmethod' objects>, '__init__': <slot wrapper '__init__' of 'staticmethod' objects>, '__new__': <built-in method __new__ of type object at 0x6941E8B0>, '__func__': <member '__func__' of 'staticmethod' objects>, '__isabstractmethod__': <attribute '__isabstractmethod__' of 'staticmethod' objects>, '__dict__': <attribute '__dict__' of 'staticmethod' objects>, '__doc__': 'staticmethod(function) -> method\\n\\nConvert a function to be a static method.\\n\\nA static method does not receive an implicit first argument.\\nTo declare a static method, use this idiom:\\n\\n class C:\\n @staticmethod\\n def f(arg1, arg2, ...):\\n ...\\n\\nIt can be called either on the class (e.g. C.f()) or on an instance\\n(e.g. C().f()). The instance is ignored except for its class.\\n\\nStatic methods in Python are similar to those found in Java or C++.\\nFor a more advanced concept, see the classmethod builtin.'})" 这个staticmethod的类是用来干什么的?
最新发布
09-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值