Gọi một chức năng của mô-đun bằng cách sử dụng tên của nó (một chuỗi)

1861
ricree 2008-08-06 17:36.

Cách tốt nhất để gọi một hàm được cung cấp một chuỗi với tên của hàm trong chương trình Python là gì. Ví dụ, giả sử rằng tôi có một mô-đun foovà tôi có một chuỗi có nội dung là "bar". Cách tốt nhất để gọi là foo.bar()gì?

Tôi cần lấy giá trị trả về của hàm, đó là lý do tại sao tôi không sử dụng eval. Tôi đã tìm ra cách thực hiện bằng cách sử dụng evalđể định nghĩa một hàm tạm thời trả về kết quả của lệnh gọi hàm đó, nhưng tôi hy vọng rằng có một cách đơn giản hơn để thực hiện việc này.

13 answers

2248
Patrick Johnmeyer 2008-08-06 17:57.

Giả sử mô-đun foovới phương pháp bar:

import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()

Bạn có thể rút ngắn dòng 2 và 3 thành:

result = getattr(foo, 'bar')()

nếu điều đó có ý nghĩa hơn đối với trường hợp sử dụng của bạn.

Bạn có thể sử dụng getattrtheo cách này trên các phương thức ràng buộc cá thể lớp, phương thức cấp mô-đun, phương thức lớp ... danh sách vẫn tiếp tục.

575
sastanin 2009-05-08 02:45.
locals()["myfunction"]()

hoặc là

globals()["myfunction"]()

người dân địa phương trả về một từ điển với bảng ký hiệu địa phương hiện tại. Gloals trả về một từ điển với bảng ký hiệu toàn cục.

356
HS. 2008-08-08 01:35.

Giải pháp của Patrick có lẽ là sạch nhất. Nếu bạn cũng cần nhận động mô-đun, bạn có thể nhập mô-đun đó như:

module = __import__('foo')
func = getattr(module, 'bar')
func()
120
Sourcegeek 2012-08-19 23:40.

Chỉ là một đóng góp đơn giản. Nếu lớp mà chúng ta cần thể hiện nằm trong cùng một tệp, chúng ta có thể sử dụng một cái gì đó như sau:

# Get class from globals and create an instance
m = globals()['our_class']()

# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')

# Call it
func()

Ví dụ:

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('you called sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')

# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')

Và, nếu không phải là một lớp:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')
111
ferrouswheel 2013-10-16 14:24.

Cho một chuỗi, với một đường dẫn python hoàn chỉnh đến một hàm, đây là cách tôi thực hiện để lấy kết quả của hàm đã nói:

import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()
60
Noname 2016-10-25 03:20.

Câu trả lời tốt nhất theo Câu hỏi thường gặp về lập trình Python sẽ là:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

Ưu điểm chính của kỹ thuật này là các chuỗi không cần phải khớp với tên của các hàm. Đây cũng là kỹ thuật chính được sử dụng để mô phỏng một cấu trúc trường hợp

45
00500005 2014-04-10 00:17.

Câu trả lời (tôi hy vọng) không ai muốn

Đánh giá hành vi thích

getattr(locals().get("foo") or globals().get("foo"), "bar")()

Tại sao không thêm tự động nhập

getattr(
    locals().get("foo") or 
    globals().get("foo") or
    __import__("foo"), 
"bar")()

Trong trường hợp chúng tôi có thêm từ điển, chúng tôi muốn kiểm tra

getattr(next((x for x in (f("foo") for f in 
                          [locals().get, globals().get, 
                           self.__dict__.get, __import__]) 
              if x)),
"bar")()

Chúng ta cần phải đi sâu hơn

getattr(next((x for x in (f("foo") for f in 
              ([locals().get, globals().get, self.__dict__.get] +
               [d.get for d in (list(dd.values()) for dd in 
                                [locals(),globals(),self.__dict__]
                                if isinstance(dd,dict))
                if isinstance(d,dict)] + 
               [__import__])) 
        if x)),
"bar")()
27
trubliphone 2012-02-14 19:55.

Đối với những gì nó đáng giá, nếu bạn cần chuyển tên hàm (hoặc lớp) và tên ứng dụng dưới dạng một chuỗi, thì bạn có thể làm điều này:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
21
tvt173 2016-12-08 08:29.

Thử cái này. Trong khi điều này vẫn sử dụng eval, nó chỉ sử dụng nó để triệu hồi hàm từ ngữ cảnh hiện tại . Sau đó, bạn có chức năng thực sự để sử dụng như bạn muốn.

Lợi ích chính đối với tôi từ việc này là bạn sẽ nhận được bất kỳ lỗi nào liên quan đến đánh giá tại thời điểm triệu hồi hàm. Sau đó, bạn sẽ chỉ nhận được các lỗi liên quan đến chức năng khi bạn gọi.

def say_hello(name):
    print 'Hello {}!'.format(name)

# get the function by name
method_name = 'say_hello'
method = eval(method_name)

# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)
13
Natdrip 2012-12-29 06:56.

không ai trong số những gì được đề xuất đã giúp tôi. Tôi đã phát hiện ra điều này mặc dù.

<object>.__getattribute__(<string name>)(<params>)

Tôi đang sử dụng python 2.66

Hi vọng điêu nay co ich

7
Serjik 2019-03-27 08:15.

Đối với câu hỏi này Làm thế nào để gọi động các phương thức trong một lớp bằng cách sử dụng gán tên phương thức cho một biến [trùng lặp] được đánh dấu là trùng lặp với biến này, tôi đăng một câu trả lời có liên quan ở đây:

Kịch bản là, một phương thức trong một lớp muốn gọi một phương thức khác trên cùng một lớp một cách động, tôi đã thêm một số chi tiết vào ví dụ ban đầu cung cấp một số kịch bản rộng hơn và rõ ràng:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.


    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

Đầu ra (Python 3.7.x)

function1: 12

function2: 12

2
Lukas 2020-07-17 05:20.

Mặc dù getattr () là phương thức thanh lịch (và nhanh hơn khoảng 7 lần), bạn có thể nhận giá trị trả về từ hàm (cục bộ, phương thức lớp, mô-đun) với eval như là thanh lịch x = eval('foo.bar')(). Và khi bạn thực hiện một số xử lý lỗi sau đó khá an toàn (nguyên tắc tương tự có thể được sử dụng cho getattr). Ví dụ với nhập mô-đun và lớp:

# import module, call module function, pass parameters and print retured value with eval():
import random
bar = 'random.randint'
randint = eval(bar)(0,100)
print(randint) # will print random int from <0;100)

# also class method returning (or not) value(s) can be used with eval: 
class Say:
    def say(something='nothing'):
        return something

bar = 'Say.say'
print(eval(bar)('nice to meet you too')) # will print 'nice to meet you' 

Khi mô-đun hoặc lớp không tồn tại (lỗi đánh máy hoặc bất cứ điều gì tốt hơn) thì NameError sẽ xuất hiện. Khi chức năng không tồn tại, thì AttributeError sẽ xuất hiện. Điều này có thể được sử dụng để xử lý các lỗi:

# try/except block can be used to catch both errors
try:
    eval('Say.talk')() # raises AttributeError because function does not exist
    eval('Says.say')() # raises NameError because the class does not exist
    # or the same with getattr:
    getattr(Say, 'talk')() # raises AttributeError
    getattr(Says, 'say')() # raises NameError
except AttributeError:
    # do domething or just...
    print('Function does not exist')
except NameError:
    # do domething or just...
    print('Module does not exist')
0
정도유 2020-07-01 22:09.

getattrgọi phương thức theo tên từ một đối tượng. Nhưng đối tượng này phải là cha của lớp đang gọi. Lớp cha có thể được lấy bởisuper(self.__class__, self)

class Base:
    def call_base(func):
        """This does not work"""
        def new_func(self, *args, **kwargs):
            name = func.__name__
            getattr(super(self.__class__, self), name)(*args, **kwargs)
        return new_func

    def f(self, *args):
        print(f"BASE method invoked.")

    def g(self, *args):
        print(f"BASE method invoked.")

class Inherit(Base):
    @Base.call_base
    def f(self, *args):
        """function body will be ignored by the decorator."""
        pass

    @Base.call_base
    def g(self, *args):
        """function body will be ignored by the decorator."""
        pass

Inherit().f() # The goal is to print "BASE method invoked."

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.

Đó phải là Đức

Đó phải là Đức

Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language