策略类中在def __init__ 之前定义的list变量和在__init__中定义的list变量的区别

本文探讨了在Python策略类中,`__init__`方法前定义的list变量与在`__init__`内定义的list变量之间的区别。当在类定义区域内初始化list变量,不同实例间可能会共享同一引用,导致数据互相影响。而在`__init__`中初始化,每个实例将拥有独立的list副本,避免了这种干扰。

策略类中在def init 之前定义的list变量和在init中定义的list变量的区别是什么?

在def init 之前定义的list变量:

class stocktestStrategy(CtaTemplate):
"""基于布林通道的交易策略"""
className = 'stocktestStrategy'
author = u'dofish'
actionMark=[]

如果有两个策略使用同一个策略类:
actionMark会应为一个策略改变而同时改变

log:
{'Tora.10': <vnxtp.trader.app.ctaStrategy.strategy.strategyTest.stocktestStrategy object at 0x7f1cf9205450>}
(u'TickTest1111', 0, '510050', 'startegy in order', 'Tora.10', ['Tora.10', 0])
(u'TickTest1111', 0, '510050', 'startegy in order', 'Tora.10', ['Tora.10', 0])
(0, '601009', 46800L, [], 4, u'TickTest222', ['Tora.10', 0])
(0, '601009', 46800L, ['Tora.10'], 5, u'TickTest1111', ['Tora.10', 0])
(0, '510050', 305900L, [], 4, u'TickTest222', ['Tora.10', 0])
{'Tora.10': <vnxtp.trader.app.ctaStrategy.strategy.strategyTest.stocktestStrategy object at 0x7f1cf9205450>, 'Tora.11': <vnxtp.trader.app.ctaStrategy.strategy.strategyTest.stocktestStrategy object at 0x7f1cf9658b50>}

log中<tickTest1111>触发下单修改actionMark 这个list对象,结果同类的另外策略<u'TickTest222> actionMark同时也变更了。

 

在 init 中定义的变量list:

def __init__(self, ctaEngine, setting):
    """Constructor"""
    super(stocktestStrategy, self).__init__(ctaEngine, setting)

    self.actionMark = [0,0]

两个同类策略就不会有干扰

log:
{'Tora.30': <vnxtp.trader.app.ctaStrategy.strategy.strategyTest.stocktestStrategy object at 0x7f40133844d0>}
(u'TickTest1111', 0, '510050', 'startegy in order', 'Tora.30', ['Tora.30', 0])
(u'TickTest1111', 0, '510050', 'startegy in order', 'Tora.30', ['Tora.30', 0])
no tick data return
(0, '510050', 1725100L, ['Tora.30'], 5, u'TickTest1111', ['Tora.30', 0])
(0, '601009', 13800L, [], 4, u'TickTest222', [0, 0])
(0, '601009', 13800L, ['Tora.30'], 6, u'TickTest1111', ['Tora.30', 0])

 

而其他类型变量没有发现这种问题,只有list是发现是这样

<think>嗯,用户想知道如何在Python中跨函数访问变量,也就是变量作用域的共享方法。首先,我得回忆一下Python的作用域规则。根据引用[2],Python没有块级作用域,if语句或者for循环里的变量在外部也能访问。但函数内部定义变量是局部变量,只能在函数内使用,外部无法直接访问,这就是局部作用域。 用户的问题涉及到跨函数访问变量,可能需要用到全局变量或者更高级的作用域处理。比如,全局变量可以在不同函数之间共享,但需要注意在函数内部使用global关键字声明,否则会被视为局部变量。比如在函数里修改全局变量时,必须用global,否则会出错。 另外,引用[3]提到,函数内定义变量是局部的,外部不能直接使用。所以如果要在多个函数间共享变量,可能需要在函数外部定义全局变量,然后在各个函数中用global引用。例如: ```python global_var = 10 def func1(): global global_var global_var += 5 def func2(): print(global_var) ``` 这样,两个函数都能访问修改同一个全局变量。 还有一种情况是嵌套函数,内部函数可以访问外部函数的变量,这时候可以使用nonlocal关键字。比如: ```python def outer(): outer_var = 20 def inner(): nonlocal outer_var outer_var += 5 inner() print(outer_var) ``` 这里inner函数可以修改outer函数的变量,但这种方式只能在嵌套结构中使用,不能跨不同的独立函数。 另外,引用[4]提到exec函数执行后的变量处理问题,可能涉及到动态生成变量,但这种情况比较复杂,可能用户的问题不需要这么深入,暂时可以忽略。 还有一种方法是使用可变对象,比如列表或字典,作为参数传递给函数,这样在函数内部修改它们的内容,外部也能看到变化。例如: ```python shared = [0] def func1(): shared[0] += 1 def func2(): print(shared[0]) ``` 因为列表是可变对象,修改其元素不会改变引用本身,所以不需要global声明,但这种方法可能不够直观,需要注意。 总结一下,跨函数访问变量的方法主要有: 1. 使用全局变量,配合global关键字。 2. 嵌套函数中使用nonlocal关键字。 3. 传递可变对象作为参数。 4. 使用类封装变量,通过实例属性共享。 5. 模块级变量,在同一个模块的不同函数中使用。 需要根据具体情况选择合适的方法。比如,如果多个函数需要共享状态,使用类可能更合适,因为全局变量容易引起副作用。而如果是简单的脚本,全局变量可能更方便。 另外,需要注意变量作用域的查找顺序:局部作用域→外部嵌套作用域→全局作用域→内置作用域。如果变量在局部作用域找不到,会逐层向上查找。 用户可能需要具体的例子来理解这些方法,所以给出不同场景的代码示例会比较好。同时,要提醒用户注意全局变量的使用可能带来的问题,比如代码的可维护性潜在的副作用。</think>在Python中跨函数访问变量主要有以下几种方法,每种方法对应不同的作用域管理策略: ### ### 一、使用全局变量(Global Variables) ```python global_var = 10 # 全局变量 def func1(): global global_var # 声明使用全局变量 global_var += 5 # 修改全局变量 def func2(): print(global_var) # 直接访问全局变量 func1() # 调用后 global_var=15 func2() # 输出 15 ``` - **作用域规则**:全局变量在模块级别定义,通过`global`声明实现跨函数访问[^3] - **注意事项**:若未声明`global`直接赋值会创建同名局部变量 ### ### 二、嵌套函数与非局部变量(Nonlocal Variables) ```python def outer(): outer_var = 20 # 闭包外层变量 def inner(): nonlocal outer_var # 声明非局部变量 outer_var *= 2 inner() print(outer_var) # 输出40 outer() ``` - **作用域规则**:`nonlocal`允许内部函数修改闭包外层变量(非全局变量)[^2] - **限制**:仅适用于嵌套函数结构 ### ### 三、通过可变对象传递 ```python shared_list = [0] # 可变对象容器 def modify_list(): shared_list[0] += 1 # 修改容器内容 def read_list(): print(shared_list[0]) modify_list() # 值变为1 read_list() # 输出1 ``` - **原理**:列表等可变对象通过引用传递,无需声明作用域关键字 - **优势**:避免全局变量污染命名空间 ### ### 四、类封装共享状态 ```python class StateManager: def __init__(self): self.shared_value = 5 manager = StateManager() def update_value(): manager.shared_value += 10 def show_value(): print(manager.shared_value) update_value() # 值变为15 show_value() # 输出15 ``` - **最佳实践**:面向对象编程中推荐使用类管理共享状态[^1] - **优势**:数据与行为封装,避免全局作用域污染 ### ### 五、模块级变量 ```python # module_shared.py module_var = 100 # func_a.py import module_shared def func_a(): module_shared.module_var -= 20 # func_b.py import module_shared def func_b(): print(module_shared.module_var) ``` - **跨模块共享**:通过导入模块访问其全局变量 - **注意事项**:需要控制多模块修改时的线程安全问题 ### ### 作用域优先级总结表 | 作用域类型 | 访问方式 | 生命周期 | |-----------------|--------------------------|----------------| | 局部变量(Local) | 函数内部直接使用 | 函数执行期间 | | 闭包变量(Enclosing) | `nonlocal`声明 | 外层函数存活期 | | 全局变量(Global) | `global`声明或直接访问 | 模块存活期 | | 内置变量(Built-in) | Python定义名称 | 解释器存活期 | [^1]: 全局变量需要显式声明才能修改,直接读取不需要声明 [^2]: 嵌套函数作用域遵循LEGB规则(Local→Enclosing→Global→Built-in) [^3]: 推荐优先使用参数传递返回值,其次才是共享作用域方案
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值