2012-11-21 40 views
17

Có khả năng tạo bản sao thực của hàm python không? Sự lựa chọn rõ ràng nhất là http://docs.python.org/2/library/copy.html nhưng tôi đọc:Cách tạo bản sao của hàm python

Nó không phải “sao chép” các chức năng và các lớp học (nông và sâu), bởi trả lại đối tượng gốc không thay đổi;

Tôi cần bản sao thực vì tôi có thể thay đổi một số thuộc tính của hàm.

Cập nhật:

Tôi nhận thức được tất cả các khả năng được đề cập trong các ý kiến. Trường hợp sử dụng của tôi dựa trên lập trình meta nơi tôi xây dựng các lớp học từ một số đặc tả khai báo. Chi tiết đầy đủ sẽ quá dài đối với SO, nhưng về cơ bản tôi có chức năng như

def do_something_usefull(self,arg): 
    self.do_work() 

Tôi sẽ thêm phương thức này vào các lớp khác nhau. Các lớp học có thể hoàn toàn không liên quan. Sử dụng các lớp mixin không phải là một lựa chọn: Tôi sẽ có nhiều hàm như vậy và sẽ kết thúc việc thêm một lớp cơ sở cho mỗi hàm. hiện tại "workaround" My sẽ được quấn chức năng này trong một "nhà máy" như thế này:

def create_do_something(): 
    def do_something_usefull(self,arg): 
     self.do_work() 

Bằng cách đó tôi luôn có được một chức năng do_something_useful mới, nhưng tôi phải quấn tất cả các chức năng của tôi như thế này.

Bạn có thể tin tưởng tôi, rằng tôi biết rằng đây không phải là chương trình OO "bình thường". Tôi biết làm thế nào để giải quyết một cái gì đó như thế "bình thường". Nhưng đây là trình tạo mã động và tôi muốn giữ mọi thứ nhẹ và đơn giản nhất có thể. Và như các hàm python là các đối tượng khá bình thường, tôi không nghĩ nó quá lạ để hỏi sao chép chúng?

+1

Sử dụng 'copy.deepcopy' nếu bạn thực sự phải. Nhưng tôi nghĩ rằng có một lỗ hổng thiết kế sâu hơn ở đâu đó. Tại sao bạn muốn sao chép các chức năng ngay từ đầu? – inspectorG4dget

+2

Bạn có thể giúp chúng tôi hiểu một chút về những gì bạn muốn làm không - câu hỏi của bạn hơi lạ/mơ hồ. Trong hàng ngàn dòng python tôi đã viết, tôi chưa bao giờ sao chép một hàm. – jfaller

+1

Nếu bạn cần duy trì trạng thái, tại sao không sử dụng các lớp học và các trường hợp? Tại sao các chức năng cần được * sao chép * bằng cách nào đó? –

Trả lời

27

Trong python2:

import types 
import functools 
def copy_func(f): 
    """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)""" 
    g = types.FunctionType(f.func_code, f.func_globals, name=f.func_name, 
          argdefs=f.func_defaults, 
          closure=f.func_closure) 
    g = functools.update_wrapper(g, f) 
    return g 

def f(x, y=2): 
    return x,y 
f.cache = [1,2,3] 
g = copy_func(f) 

print(f(1)) 
print(g(1)) 
print(g.cache) 
assert f is not g 

mang

(1, 2) 
(1, 2) 
[1, 2, 3] 

Trong Python3:

import types 
import functools 

def copy_func(f): 
    """Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)""" 
    g = types.FunctionType(f.__code__, f.__globals__, name=f.__name__, 
          argdefs=f.__defaults__, 
          closure=f.__closure__) 
    g = functools.update_wrapper(g, f) 
    g.__kwdefaults__ = f.__kwdefaults__ 
    return g 

def f(arg1, arg2, arg3, kwarg1="FOO", *args, kwarg2="BAR", kwarg3="BAZ"): 
    return (arg1, arg2, arg3, args, kwarg1, kwarg2, kwarg3) 
f.cache = [1,2,3] 
g = copy_func(f) 

print(f(1,2,3,4,5)) 
print(g(1,2,3,4,5)) 
print(g.cache) 
assert f is not g 

sản lượng

(1, 2, 3, (5,), 4, 'BAR', 'BAZ') 
(1, 2, 3, (5,), 4, 'BAR', 'BAZ') 
[1, 2, 3] 
+4

Từ điển hàm cũng phải được sao chép: 'g .__ dict __. Update (f .__ dict __)' –

+0

Có 'func_code' (và bạn bè) tương đương Python 2 của' __code__' (và bạn bè) không? – weberc2

+0

@weberc: Vâng, đúng vậy. Tôi đã cập nhật câu trả lời cho Python3. – unutbu