簡體   English   中英

如何在ipython中的類中自動重載函數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM