普通类函数,@classmethod,@staticmethod,@property,@some_property.setter函数认识

本文深入探讨Python中的类方法、静态方法、属性方法及其实现原理,通过实例展示不同方法的调用过程和作用,帮助读者理解并掌握Python类中方法的使用。
# coding=utf-8
class MyClass(object):
    def __init__(self):
        self._some_property = "properties are nice"
        self._some_other_property = "VERY nice"

    def normal_method(*args, **kwargs):
        print("{0},{1}".format(args, kwargs))

    @classmethod
    def class_method(*args, **kwargs):
        print("{0},{1}".format(args, kwargs))

    @staticmethod
    def static_method(*args, **kwargs):
        print("{0},{1}".format(args, kwargs))

    @property
    def some_property(self, *args, **kwargs):
        print("{0},{1},{2}".format(self, args, kwargs))
        return self._some_property

    @property
    def some_other_property(self, *args, **kwargs):
        print("{0},{1},{2}".format(self, args, kwargs))
        return self._some_other_property

    @some_property.setter
    def some_property(self, *args, **kwargs):
        print("{0},{1},{2}".format(self, args, kwargs))
        self._some_property = args[0]


o = MyClass( )
# 1.普通函数——》省略了self,所以会把第一个参数作为类的实例(就像是self,可以自定义)
print(o.normal_method)  # <bound method MyClass.normal_method of <__main__.MyClass object at 0x000002F090756748>>
print(o.normal_method( ))  # (<__main__.MyClass object at 0x000001707D686748>,),{}
print(o.normal_method(1, 2, x = 3, y = 4))  # (<__main__.MyClass object at 0x000001707D686748>, 1, 2),{'x': 3, 'y': 4}

# 2.类函数——》类方法的第一个参数永远是该类的实例
print(o.class_method)  # <bound method MyClass.class_method of <class '__main__.MyClass'>>
print(o.class_method( ))  # (<class '__main__.MyClass'>,),{}
print(o.class_method(1, 2, x = 3, y = 4))  # (<class '__main__.MyClass'>, 1, 2),{'x': 3, 'y': 4}

# 3.静态方法——》除了你调用时传入的参数以外,没有其他的参数
print(o.static_method)  # <function MyClass.static_method at 0x000001725F2A4F78>
print(o.static_method( ))  # (),{}
print(o.static_method(1, 2, x = 3, y = 4))  # (1, 2),{'x': 3, 'y': 4}

# 4.默认是获取类属性的函数
print(o.some_property)
# <__main__.MyClass object at 0x000001B7AF701E48>,(),{}
# properties are nice

# 5.默认是获取类属性的函数
print(o.some_other_property)
# <__main__.MyClass object at 0x000002948A091DC8>,(),{}
# VERY nice

# 6.设置类属性的函数
test = o.some_property = "groovy"
print(test)
# <__main__.MyClass object at 0x000001D3518A1E88>,('groovy',),{}
# groovy

修改::方法必须有第一个形参,通常叫做 'self',,未解析的引用 'self',,未解析的引用 'self',未解析的引用 'self',类 'FollowAnalysisModule' 的未解析的特性引用 'run_analysis',,重复的代码段(150 行长),,重复的代码段(4 行长),,重复的代码段(8 行长),,,未使用局部变量 'follow_engine' 的值,,代码# ====== 跟随分析模块完整代码 ====== # !/usr/bin/env python3 # -*- coding: utf-8 -*- """ 彩票跟随分析模块(独立完整版) 包含分析引擎和UI,无需外部依赖 """ import json import os import sys import time import logging import threading import random import pandas as pd from pathlib import Path import tkinter as tk from tkinter import ttk, scrolledtext, messagebox from collections import defaultdict, Counter from typing import List, Dict, Optional, Tuple import chardet CORE_DIR = Path(__file__).parent.parent / "core" if str(CORE_DIR) not in sys.path: sys.path.insert(0, str(CORE_DIR)) # 配置日志系统 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) logger = logging.getLogger('FollowAnalysisSystem') # ====== 事件类型定义 ====== class EventType: DATA_SUBMIT = "data_submit" ANALYSIS_RESULT = "analysis_result" MODULE_RUN = "module_run" MODULE_READY = "module_ready" MODULE_COMPLETE = "module_complete" UI_UPDATE = "ui_update" ERROR = "error" class Event: def __init__(self, event_id: int, event_type: str, source: str, target: str, data: dict = None, token: str = None): self.event_id = event_id self.type = event_type self.source = source self.target = target self.data = data or {} self.token = token # ====== 事件中心 ====== class EventCenter: _instance = None _lock = threading.Lock() def __new__(cls): if cls._instance is None: with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._subscribers = defaultdict(list) return cls._instance def subscribe(self, event_type, handler, token=None): if not callable(handler): raise ValueError("handler必须是可调用函数") self._subscribers[event_type].append((handler, token)) def publish(self, event): for handler, token in self._subscribers.get(event.type, []): if token is None or token == event.token: try: handler(event) except Exception as e: logger.error(f"事件处理失败: {str(e)}") # 创建全局事件中心实例 event_center = EventCenter() # ====== 前端加载器 ====== class FrontendLoader: def __init__(self): self._ui_instance = None logger.info("前端加载器已初始化") logger.info("[模块状态] FrontendLoader: ✅ 已加载") @property def ui(self): return self._ui_instance @ui.setter def ui(self, value): self._ui_instance = value logger.info("UI实例已设置到前端加载器") # ====== 彩票数据接口类 ====== class LotteryDataInterface: """彩票数据接口类""" @staticmethod def detect_encoding(file_path: str) -> str: """检测文件编码""" try: with open(file_path, 'rb') as f: rawdata = f.read(100000) result = chardet.detect(rawdata) encoding = result['encoding'] or 'gb2312' logger.info(f"检测到文件编码: {encoding} (置信度: {result['confidence']:.1%})") return encoding except Exception as error: logger.warning(f"编码检测失败, 使用默认编码: {str(error)}") return 'gb2312' @staticmethod def preprocess_data(df: pd.DataFrame) -> pd.DataFrame: """预处理数据""" try: # 重命名列 column_map = { '开奖期号': '期号', '前区1': '前1', '前区2': '前2', '前区3': '前3', '前区4': '前4', '前区5': '前5', '后区1': '后1', '后区2': '后2' } for orig_col, new_col in column_map.items(): if orig_col in df.columns: df.rename(columns={orig_col: new_col}, inplace=True) # 合并号码列 front_cols = [col for col in ['前1', '前2', '前3', '前4', '前5'] if col in df.columns] back_cols = [col for col in ['后1', '后2'] if col in df.columns] if front_cols: df['前区号码'] = df[front_cols].values.tolist() if back_cols: df['后区号码'] = df[back_cols].values.tolist() # 按期号排序 if '期号' in df.columns: df = df.sort_values('期号') logger.info(f"数据预处理完成,共{len(df)}期数据") return df except Exception as error: logger.error(f"数据预处理失败: {str(error)}") raise @staticmethod def load_data(file_path: str) -> Optional[pd.DataFrame]: """加载数据文件""" if not os.path.exists(file_path): logger.error(f"数据文件不存在: {file_path}") return None encodings = ['gb2312', 'utf-8', 'gbk', 'utf-16'] detected_encoding = LotteryDataInterface.detect_encoding(file_path) if detected_encoding not in encodings: encodings.insert(0, detected_encoding) for encoding in encodings: try: df = pd.read_csv(file_path, encoding=encoding) logger.info(f"成功使用 {encoding} 编码加载数据") return LotteryDataInterface.preprocess_data(df) except UnicodeDecodeError: continue except Exception as decode_error: logger.error(f"加载数据时出错: {str(decode_error)}") continue logger.error("尝试了所有编码方式仍无法加载数据") return None # ====== 跟随分析核心类 ====== class FollowingAnalyzer: """跟随分析核心类""" def __init__(self, df: pd.DataFrame): self.df = df.tail(500).copy() if len(df) >= 500 else df.copy() self.last_update_time = time.time() logger.info(f"初始化分析器,使用{len(self.df)}期数据") def analyze_front_more(self) -> List[str]: """分析前区多推荐""" front_following, _ = self._analyze_following() return self._get_most_common_numbers(front_following, "前推荐多") def analyze_front_less(self) -> List[str]: """分析前区少推荐""" front_following, _ = self._analyze_following() return self._get_least_common_numbers(front_following, "前推荐少") def analyze_back_more(self) -> List[str]: """分析后区多推荐""" _, back_following = self._analyze_following() return self._get_most_common_numbers(back_following, "后推荐多") def analyze_back_less(self) -> List[str]: """分析后区少推荐""" _, back_following = self._analyze_following() return self._get_least_common_numbers(back_following, "后推荐少") def _analyze_following(self) -> Tuple[Dict[int, Counter], Dict[int, Counter]]: """分析前后区号码的跟随关系""" front_following = defaultdict(Counter) back_following = defaultdict(Counter) for i in range(len(self.df) - 1): current = self.df.iloc[i] next_draw = self.df.iloc[i + 1] if '前区号码' in current and '前区号码' in next_draw: current_front = current['前区号码'] next_front = next_draw['前区号码'] for num in current_front: front_following[num].update(next_front) if '后区号码' in current and '后区号码' in next_draw: current_back = current['后区号码'] next_back = next_draw['后区号码'] for num in current_back: back_following[num].update(next_back) logger.info(f"跟随分析完成,前区{len(front_following)}种,后区{len(back_following)}种跟随关系") return front_following, back_following @staticmethod def _get_most_common_numbers(following_dict: Dict[int, Counter], label: str, top_n: int = 5) -> List[str]: all_numbers = Counter() for counter in following_dict.values(): all_numbers.update(counter) most_common = [f"{num:02d}" for num, _ in all_numbers.most_common(top_n)] logger.debug(f"{label}号码: {most_common}") return most_common @staticmethod def _get_least_common_numbers(following_dict: Dict[int, Counter], label: str, top_n: int = 5) -> List[str]: all_numbers = Counter() for counter in following_dict.values(): all_numbers.update(counter) least_common = [f"{num:02d}" for num, _ in all_numbers.most_common()[-top_n:]] logger.debug(f"{label}号码: {least_common}") return least_common # ====== 跟随分析引擎 ====== class FollowAnalysisEngine: def __init__(self): self.module_name = "follow_analysis_engine" self._setup_subscriptions() logger.info("跟随分析引擎已初始化") logger.info("跟随分析引擎已启动,等待UI指令...") logger.info(f"模块ID: {self.module_name}") def _setup_subscriptions(self): """设置事件订阅""" event_center.subscribe(EventType.MODULE_RUN, self._handle_module_run, token=self.module_name) def _handle_module_run(self, event): """处理模块运行事件""" if event.target != self.module_name: return logger.info("跟随分析引擎开始处理") try: # 模拟跟随分析逻辑 front_rec_more = sorted(random.sample(range(1, 36), 5)) front_rec_less = sorted(random.sample(range(1, 36), 5)) back_rec_more = sorted(random.sample(range(1, 13), 2)) back_rec_less = sorted(random.sample(range(1, 13), 2)) # 发布分析结果 result_event = Event( event_id=int(time.time()), event_type=EventType.ANALYSIS_RESULT, source=self.module_name, target='pool', data={ "前推荐多": front_rec_more, "前推荐少": front_rec_less, "后推荐多": back_rec_more, "后推荐少": back_rec_less }, token=self.module_name ) event_center.publish(result_event) logger.info("跟随分析结果已发布") except Exception as e: logger.error(f"跟随分析失败: {str(e)}") error_event = Event( event_id=int(time.time()), event_type=EventType.ERROR, source=self.module_name, target='pool', data={"error": str(e)}, token=self.module_name ) event_center.publish(error_event) # ====== 跟随分析UI模块 ====== class FollowAnalysisModule: FIXED_LABELS = ["前推荐多", "前推荐少", "后推荐多", "后推荐少"] def __init__(self, module_name: str = "follow_analysis", master=None): self.module_name = module_name self.master = master or self._create_root_window() self.value_vars = {} self.data_lock = threading.Lock() self.analysis_start_time = 0 self.run_button = None self.dynamic_data = {label: "" for label in self.FIXED_LABELS} self.result_text = None logger.info("跟随分析UI模块已初始化") self._create_ui() self._setup_event_handlers() self._setup_timeout_detection() logger.info("[模块状态] follow_analysis.FollowAnalysisModule: ✅ 已加载") @staticmethod def _create_root_window(): """创建主窗口""" main_window = tk.Tk() main_window.title("跟随分析模块") main_window.geometry("800x500") return main_window def _create_ui(self): """创建用户界面""" main_frame = ttk.Frame(self.master) main_frame.pack(fill='both', expand=True, padx=10, pady=5) # 标题区域 title_frame = ttk.Frame(main_frame) title_frame.pack(fill='x', pady=5) ttk.Label(title_frame, text="跟随分析", font=("楷体", 14, "bold")).pack(side='left') ttk.Label(title_frame, text=f"模块ID: {self.module_name}", font=("宋体", 10)).pack(side='right', padx=10) # 动态数据区域 self._create_dynamic_section(main_frame) # 结果展示区域 self._create_result_section(main_frame) # 按钮区域 self._create_button_section(main_frame) def _create_dynamic_section(self, parent): """创建动态数据显示区域""" dynamic_frame = ttk.LabelFrame(parent, text="动态区") dynamic_frame.pack(fill='x', padx=10, pady=5, ipadx=5, ipady=5) for label in self.FIXED_LABELS: frame = ttk.Frame(dynamic_frame) frame.pack(fill='x', padx=5, pady=2) ttk.Label(frame, text=f"{label}:", width=10, anchor='e').pack(side='left', padx=(0, 5)) self.value_vars[label] = tk.StringVar() ttk.Entry(frame, textvariable=self.value_vars[label], state='readonly', width=30).pack(side='left', fill='x', expand=True) def _create_result_section(self, parent): """创建结果展示区域""" result_frame = ttk.LabelFrame(parent, text="分析结果") result_frame.pack(fill='both', expand=True, padx=10, pady=5) self.result_text = scrolledtext.ScrolledText(result_frame, wrap=tk.WORD, height=10) self.result_text.pack(fill='both', expand=True, padx=5, pady=5) self._update_result_text("点击'运行'按钮开始分析…") def _create_button_section(self, parent): """创建按钮区域""" button_frame = ttk.Frame(parent) button_frame.pack(fill='x', padx=10, pady=10) btn_container = ttk.Frame(button_frame) btn_container.pack(side='right', padx=5) buttons_info = [ ("运行", self.run_analysis), ("清除", self._clear_data), ("保存", self.save_data), ("刷新", self._refresh_data) ] for btn_text, command in buttons_info: btn = ttk.Button(btn_container, text=btn_text, command=command) if btn_text == "运行": self.run_button = btn btn.pack(side='left', padx=5) def _setup_event_handlers(self): """设置事件处理器""" event_center.subscribe(EventType.ANALYSIS_RESULT, self._handle_analysis_result, token=self.module_name) event_center.subscribe(EventType.ERROR, self._handle_error, token=self.module_name) logger.info("事件处理器已注册") def _setup_timeout_detection(self): """设置超时检测机制""" def check_timeout(): if self.analysis_start_time > 0: elapsed = time.time() - self.analysis_start_time if elapsed > 15: # 15秒超时 self._handle_analysis_timeout() self.master.after(1000, check_timeout) self.master.after(1000, check_timeout) logger.info("超时检测已启动") def _handle_analysis_result(self, event): """处理分析结果事件""" if event.source != "follow_analysis_engine": return self._update_dynamic_data(event.data) self._update_ui() self._complete_analysis() def _handle_error(self, event): """处理错误事件""" error_msg = event.data.get('error', '未知错误') logger.error(f"接收到错误: {error_msg}") self._update_result_text(f"错误: {error_msg}") self._complete_analysis() def _handle_analysis_timeout(self): """处理分析超时""" self.analysis_start_time = 0 if self.run_button: self.run_button.config(state='normal') self._update_result_text("分析超时,请检查分析引擎状态") logger.error("分析超时") def _complete_analysis(self): """完成分析后的通用操作""" self.analysis_start_time = 0 if self.run_button: self.run_button.config(state='normal') def run_analysis_threaded(): self.run_button.config(state=tk.DISABLED) self.analysis_start_time = time.time() self._update_result_text("分析中,请稍候…") thread = threading.Thread(target=self._run_analysis_task) thread.start() def _run_analysis_task(self): """运行分析""" try: if self.run_button: self.run_button.config(state=tk.DISABLED) self.analysis_start_time = time.time() self._update_result_text("分析中,请稍候…") # 发送运行事件 run_event = Event( event_id=int(time.time()), event_type=EventType.MODULE_RUN, source=self.module_name, target="follow_analysis_engine", data={"command": "start_analysis"}, token=self.module_name ) event_center.publish(run_event) logger.info("已发送运行指令到跟随分析引擎") except Exception as ex: logger.error(f"运行分析时出错: {str(ex)}") self._update_result_text(f"错误: {str(ex)}") if self.run_button: self.run_button.config(state='normal') def _update_dynamic_data(self, result): """更新动态数据""" with self.data_lock: for label in self.FIXED_LABELS: if label in result: value = result[label] display_value = ', '.join(map(str, value)) if isinstance(value, list) else str(value) self.dynamic_data[label] = display_value self.value_vars[label].set(display_value) def _update_ui(self): """更新结果界面""" result_str = "=== 分析完成 ===\n\n" result_str += f"时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n" for label in self.FIXED_LABELS: value = self.dynamic_data.get(label, "无数据") result_str += f"{label}: {value}\n" result_str += "\n=== 分析结束 ===" self._update_result_text(result_str) def _update_result_text(self, message): """更新结果文本框""" if self.result_text: self.result_text.config(state=tk.NORMAL) self.result_text.delete(1.0, tk.END) self.result_text.insert(tk.END, message) self.result_text.config(state=tk.DISABLED) def _clear_data(self): """清除数据""" for label in self.FIXED_LABELS: self.value_vars[label].set("") self.dynamic_data[label] = "" self._update_result_text("数据已清除") logger.info("动态区数据已清除") def save_data(self): """保存数据到指定路径""" try: # 指定保存路径 save_path = r"C:\Users\Administrator\Desktop\project\modules" os.makedirs(save_path, exist_ok=True) filename = os.path.join(save_path, f"follow_analysis_{time.strftime('%Y%m%d_%H%M%S')}.json") with open(filename, 'w', encoding='utf-8') as f: json.dump(self.dynamic_data, f, indent=2, ensure_ascii=False) self._update_result_text(f"数据已保存到: {filename}\n") logger.info(f"数据已保存到: {filename}") except Exception as ex: logger.error(f"保存失败: {ex}") messagebox.showerror("保存错误", f"保存数据时出错: {str(ex)}") def _refresh_data(self): """刷新数据""" self._update_ui() self._update_result_text("数据已刷新\n") logger.info("数据已刷新") def update_ui(self, data): """更新UI(供前端加载器调用)""" if 'update_type' in data and data['update_type'] == 'follow_data': self._update_dynamic_data(data.get('data', {})) self._update_ui() # ====== 主函数 ====== def main(): """主函数""" try: # 初始化根窗口 root = tk.Tk() root.title("跟随分析模块") root.geometry("800x500") # 初始化前端加载器 frontend_loader = FrontendLoader() # 初始化跟随分析模块 follow_module = FollowAnalysisModule(master=root) # 设置UI实例到前端加载器 frontend_loader.ui = follow_module # 初始化跟随分析引擎 follow_engine = FollowAnalysisEngine() logger.info("等待来自 'follow_analysis' 的指令") root.mainloop() except Exception as e: logger.error(f"应用启动失败: {str(e)}") messagebox.showerror("错误", f"应用启动失败: {str(e)}") if __name__ == "__main__": main()
09-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值