[英]How to autoreload function in class in ipython?
我使用ipython的重新加載功能,並且可以自動重新加載代碼更改。 但是我發現,如果我向類中添加了一些新功能,則該新功能將無法自動重新加載。 誰能幫助解決這個問題? 例如,我有一個包含代碼的main.py文件:
class A():
def f(self):
print "in f"
if __name__ == '__main__':
from main import *
a = A()
a.f()
當我在ipython中使用run -i main.py
時,我可以修改函數f並在ipython shell中使用af()
來使新函數運行。 但是,如果我想添加一個新函數,例如,將類定義為:
class A():
def f(self):
print "in f"
def g(self):
print "in g"
我不能使用ag()
運行新函數,我將得到:
AttributeError: A instance has no attribute 'g'
因此,我的問題是如何在不重新運行整個代碼的情況下自動重載類中的新函數?
以我的經驗,僅使用自動重裝無法實現您想要的。 存在一個技巧並將其放置在末尾。
當您向類添加新函數時,它將在python解釋器中編譯為其他類對象。 從現在開始,該類對象將與您的類實例的__class__
屬性不同。
我在ipython中執行了以下操作來驗證這一點(假設自動重載已激活):
import testmodule
print(id(testmodule.TestClass)) #1
inst = testmodule.TestClass()
print(id(inst.__class__)) #2 you will observer the same output as #1
# then you add a function to your class
print(id(testmodule.TestClass)) #3 you will observer a different output as #1
這表明您在向該類引入新方法時定義了一個新類,並且原始實例inst
不跟蹤更改。
因此,解決該問題的技巧是:
inst.__class__ = testmodule.TestClass
定義新方法之后。
您可以使用%autoreload
In [75]: import eg
In [76]: eg.f()
100
[1] + 4395 suspended ipython
(si)
[11:54:28] ado@crystal ~
> vim eg.py
(si)
[11:54:41] ado@crystal ~
> %
[1] + 4395 continued ipython
In [77]: %load_ext autoreload
In [78]: eg.f()
100
In [79]: %autoreload 2 # The option 2 will reload every time. Check the docs to see what option is most appropriate
[1] + 4395 suspended ipython
(si)
[11:55:59] ado@crystal ~
> vim eg.py # Change code
(si)
[11:56:05] ado@crystal ~
> %
[1] + 4395 continued ipython
In [83]: eg.f()
hi
添加新代碼的方式相同
In [85]: eg.g()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-85-1c70170112b5> in <module>()
----> 1 eg.g()
AttributeError: module 'eg' has no attribute 'g'
[1] + 4395 suspended ipython
(si)
[12:02:59] ado@crystal ~
> vim eg.py # Add new code
(si)
[12:03:21] ado@crystal ~
> %
[1] + 4395 continued ipython
In [86]: eg.g()
G!
對於任何類定義,例如
class Foo:
pass
您可以在運行時向其實例添加屬性
>>> foo = Foo()
>>> foo.bar = 23
>>> print(foo.bar)
23
也就是說,對於一個實例。 更改類定義(即屬性)並期望所做的更改會自動傳播到您的活動實例會適得其反(並非不可能)
如果您仍在考慮如何在ipython中重新加載模塊,請使用我從github上的一個帥哥那里獲得的要點 。 基本上
# for auto-reloading external modules
# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython
%load_ext autoreload
%autoreload 2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.