পদ্ধতির পরামিতিগুলির নাম কীভাবে পাবেন?


236

পাইথন ফাংশন দেওয়া:

def a_method(arg1, arg2):
    pass

আমি কীভাবে আর্গুমেন্টের নম্বর এবং নামগুলি বের করতে পারি। অর্থাত, আমার কাছে একটি রেফারেন্স রয়েছে func, আমি func.[something]ফিরে আসতে চাই ("arg1", "arg2")

এর ব্যবহারের পরিস্থিতিটি হ'ল আমার কাছে একটি ডেকরেটর রয়েছে এবং আমি পদ্ধতিটি যুক্তিগুলি একই ক্রমে ব্যবহার করতে চাই যাতে তারা কী হিসাবে প্রকৃত ফাংশনের জন্য উপস্থিত হয়। যেমন, "a,b"আমি কল করার সময় সাজসজ্জারটি কীভাবে মুদ্রিত হবে a_method("a", "b")?


1
প্রায় অনুরূপ প্রশ্নের উত্তরের ভিন্ন তালিকার জন্য, এই অন্যান্য
স্ট্যাকওভারফ্লো

1
আপনার শিরোনাম বিভ্রান্তিমূলক: যখন কেউ 'পদ্ধতি' শব্দটি 'ফাংশন' শব্দটি ছড়িয়ে দেয়, তখন কেউ সাধারণত একটি শ্রেণিবদ্ধের পদ্ধতি চিন্তা করে। ফাংশনের জন্য, আপনার নির্বাচিত উত্তরটি (জাউনি কে। সিপ্পেনেন থেকে) ভাল। তবে (শ্রেণি) পদ্ধতির জন্য, এটি কাজ করছে না এবং পরিদর্শন সমাধান (ব্রায়ান থেকে) ব্যবহার করা উচিত।
জুহ_আগস্ট

উত্তর:


351

inspectমডিউলটি একবার দেখুন - এটি আপনার জন্য বিভিন্ন কোড অবজেক্ট বৈশিষ্ট্যের পরিদর্শন করবে।

>>> inspect.getfullargspec(a_method)
(['arg1', 'arg2'], None, None, None)

অন্যান্য ফলাফলগুলি হ'ল * আরগস এবং ** কাওয়ার্গ্স ভেরিয়েবলের নাম এবং প্রদত্ত ডিফল্ট। অর্থাত।

>>> def foo(a, b, c=4, *arglist, **keywords): pass
>>> inspect.getfullargspec(foo)
(['a', 'b', 'c'], 'arglist', 'keywords', (4,))

দ্রষ্টব্য যে কিছু কলযোগ্য পাইথনের কিছু কিছু বাস্তবায়নে অন্তরীক্ষণযোগ্য নাও হতে পারে। উদাহরণস্বরূপ, সিপিথনে, সি-তে সংজ্ঞায়িত কিছু বিল্ট-ইন ফাংশনগুলি তাদের আর্গুমেন্ট সম্পর্কে কোনও মেটাডেটা সরবরাহ করে না। ফলস্বরূপ, আপনি ValueErrorযদি inspect.getfullargspec()একটি অন্তর্নির্মিত ফাংশন ব্যবহার করেন তবে আপনি একটি পাবেন ।

পাইথন ৩.৩ থেকে আপনি inspect.signature()কলযোগ্য বস্তুর কল স্বাক্ষরটি দেখতে ব্যবহার করতে পারেন:

>>> inspect.signature(foo)
<Signature (a, b, c=4, *arglist, **keywords)>

29
কোডটি কীভাবে সম্ভবত জানতে পারে যে ডিফল্ট প্যারামিটারটি (4,)মূলত কীওয়ার্ড প্যারামিটারের সাথে সামঞ্জস্য করে c?
ফতুহোকু

63
@ ফাতুহোকু আমিও একই জিনিসটি ভাবছিলাম। দেখা যাচ্ছে এটি অস্পষ্ট নয় যেহেতু আপনি কেবল শেষে একটি ডিফল্ট যুক্তি যুক্ত করতে পারেন a দস্তাবেজগুলি থেকে: "যদি এই টিপলটিতে n উপাদান থাকে তবে তারা
আর্গগুলিতে

9
আমার মনে হয় যেহেতু পাইথন ৩.x গেটগারস্পেক (...) এর পরিবর্তে ইন্সপেক্টর.সাইনচার (ফানক)
ডিয়েগো আন্ড্রেস দাজ এস্পিনোজা

2
সংস্করণ ২.6 এ পরিবর্তিত হয়েছে: একটি নামযুক্ত টিপল আরগস্পেক (অর্গস, ভারার্গস, কীওয়ার্ডস, ডিফল্ট) প্রদান করে।
theannouncer

4
একেবারে ঠিক, @ DiegoAndrésDíazEspinoza হয় - পাইথন 3, inspect.getargspecহয় অবচিত কিন্তু প্রতিস্থাপন inspect.getfullargspec
j08lue

100

সিপিথনে আর্গুমেন্টের সংখ্যা

a_method.func_code.co_argcount

এবং তাদের নাম শুরুতে

a_method.func_code.co_varnames

এগুলি সিপিথনের বাস্তবায়ন বিবরণ, সুতরাং এটি পাইথনের অন্যান্য বাস্তবায়নে যেমন আয়রন পাইথন এবং জাইথনের ক্ষেত্রে সম্ভবত কাজ করে না।

"পাস-থ্রু" আর্গুমেন্ট স্বীকার করার একটি বহনযোগ্য উপায় হ'ল স্বাক্ষর দিয়ে আপনার ফাংশনটি সংজ্ঞায়িত করা func(*args, **kwargs)। এটি উদাহরণস্বরূপ ম্যাটপ্লোটিলিবতে প্রচুর ব্যবহৃত হয় , যেখানে বাইরের এপিআই স্তরটি নিম্ন-স্তরের এপিআইতে প্রচুর কীওয়ার্ড আর্গুমেন্টগুলি দেয় passes


co_varnames স্ট্যান্ডার্ড পাইথন নিয়ে কাজ করে তবে এই পদ্ধতিটি পছন্দনীয় নয় কারণ এটি অভ্যন্তরীণ আর্গুমেন্টগুলিও প্রদর্শন করবে।
ম্যাটকে

11
কেন মেথড.ফুনক_কোড.কম_ভর্মনামস [: aMethod.func_code.co_argcount] ব্যবহার করবেন না?
হচল

পরে যুক্তি দিয়ে কাজ করা নয় *args, যেমন:def foo(x, *args, y, **kwargs): # foo.__code__.co_argcount == 1
নিকোলে মাখালিন


পরিবর্তে পরিদর্শন ব্যবহার করুন। অন্যথায়, আপনার কোডটি ফ্যান্টচুলস.রাপগুলি 3.4+ এ ভাল কাজ করে না। দেখুন stackoverflow.com/questions/147816/...
ব্রায়ান McCutchon

22

ডেকোরেটার পদ্ধতিতে, আপনি এই পদ্ধতিতে মূল পদ্ধতির যুক্তি তালিকাভুক্ত করতে পারেন:

import inspect, itertools 

def my_decorator():

        def decorator(f):

            def wrapper(*args, **kwargs):

                # if you want arguments names as a list:
                args_name = inspect.getargspec(f)[0]
                print(args_name)

                # if you want names and values as a dictionary:
                args_dict = dict(itertools.izip(args_name, args))
                print(args_dict)

                # if you want values as a list:
                args_values = args_dict.values()
                print(args_values)

যদি আপনার **kwargsজন্য গুরুত্বপূর্ণ হয় তবে এটি কিছুটা জটিল হবে:

        def wrapper(*args, **kwargs):

            args_name = list(OrderedDict.fromkeys(inspect.getargspec(f)[0] + kwargs.keys()))
            args_dict = OrderedDict(list(itertools.izip(args_name, args)) + list(kwargs.iteritems()))
            args_values = args_dict.values()

উদাহরণ:

@my_decorator()
def my_function(x, y, z=3):
    pass


my_function(1, y=2, z=3, w=0)
# prints:
# ['x', 'y', 'z', 'w']
# {'y': 2, 'x': 1, 'z': 3, 'w': 0}
# [1, 2, 3, 0]

এই উত্তরটি আংশিকভাবে অপ্রচলিত এবং আপডেট হওয়া উচিত।
ইমাগো

15

আমি মনে করি আপনি যা খুঁজছেন তা স্থানীয় পদ্ধতি -


In [6]: def test(a, b):print locals()
   ...: 

In [7]: test(1,2)              
{'a': 1, 'b': 2}

7
এটি এখানে কোনও ফাংশনের বাইরে অকেজো যা এখানে আগ্রহের প্রসঙ্গে (ডেকোরেটর)।
পাইওটর ডব্রোগোস্ট

8
আসলে আমি যা খুঁজছিলাম তা যদিও এটি এখানে প্রশ্নের উত্তর নয়।
জাবাবেংরিন্দর

15

পাইথন 3 সংস্করণটি হ'ল:

def _get_args_dict(fn, args, kwargs):
    args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount]
    return {**dict(zip(args_names, args)), **kwargs}

পদ্ধতিটি একটি অভিধান প্রদান করে যা দুটি আরগ এবং কাওয়ার্গ যুক্ত করে।


লক্ষ্য করুন যে [:fn.__code__.co_argcount]আপনি যদি ফাংশনটি যুক্তিগুলি সন্ধান করেন তবে এটি খুব গুরুত্বপূর্ণ otherwise
সোরেন জর্নস্ট্যাড

13

এখানে এমন কিছু যা আমি মনে করি আপনি ডেকোরেটর ব্যবহার করে যা চান তার জন্য কাজ করবে।

class LogWrappedFunction(object):
    def __init__(self, function):
        self.function = function

    def logAndCall(self, *arguments, **namedArguments):
        print "Calling %s with arguments %s and named arguments %s" %\
                      (self.function.func_name, arguments, namedArguments)
        self.function.__call__(*arguments, **namedArguments)

def logwrap(function):
    return LogWrappedFunction(function).logAndCall

@logwrap
def doSomething(spam, eggs, foo, bar):
    print "Doing something totally awesome with %s and %s." % (spam, eggs)


doSomething("beans","rice", foo="wiggity", bar="wack")

এটি চালান, এটি নিম্নলিখিত আউটপুট উত্পাদন করবে:

C:\scripts>python decoratorExample.py
Calling doSomething with arguments ('beans', 'rice') and named arguments {'foo':
 'wiggity', 'bar': 'wack'}
Doing something totally awesome with beans and rice.

11

পাইথন 3.5+:

অবচয়করণ সতর্কতা: inspect.getargspec () অবমূল্যায়ন করা হয়েছে, পরিবর্তে inspect.signature () ব্যবহার করুন

অতীতে:

func_args = inspect.getargspec(function).args

এখন:

func_args = list(inspect.signature(function).parameters.keys())

পরীক্ষা করার জন্য:

'arg' in list(inspect.signature(function).parameters.keys())

আমাদের ফাংশন 'ফাংশন' দেওয়া আছে যা আর্গুমেন্ট 'আর্গ' নেয়, এটি সত্য হিসাবে অন্যথায় মিথ্যা হিসাবে মূল্যায়ন করবে।

পাইথন কনসোল থেকে উদাহরণ:

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32
>>> import inspect
>>> 'iterable' in list(inspect.signature(sum).parameters.keys())
True

7

পাইথন ৩. Signatureহাতে থাকা অবজেক্টের সাথে , আর্গুমেন্টের নামের সাথে মানগুলির মধ্যে ম্যাপিংয়ের একটি সহজ উপায় হ'ল স্বাক্ষর ব্যবহার করেbind() পদ্ধতিটি!

উদাহরণস্বরূপ, এখানে মানচিত্র প্রিন্ট করার জন্য এখানে একটি সজ্জাকারক রয়েছে:

import inspect

def decorator(f):
    def wrapper(*args, **kwargs):
        bound_args = inspect.signature(f).bind(*args, **kwargs)
        bound_args.apply_defaults()
        print(dict(bound_args.arguments))

        return f(*args, **kwargs)

    return wrapper

@decorator
def foo(x, y, param_with_default="bars", **kwargs):
    pass

foo(1, 2, extra="baz")
# This will print: {'kwargs': {'extra': 'baz'}, 'param_with_default': 'bars', 'y': 2, 'x': 1}

6

এখানে কোনও মডিউল ব্যবহার না করে ফাংশন পরামিতিগুলি পাওয়ার আরও একটি উপায়।

def get_parameters(func):
    keys = func.__code__.co_varnames[:func.__code__.co_argcount][::-1]
    sorter = {j: i for i, j in enumerate(keys[::-1])} 
    values = func.__defaults__[::-1]
    kwargs = {i: j for i, j in zip(keys, values)}
    sorted_args = tuple(
        sorted([i for i in keys if i not in kwargs], key=sorter.get)
    )
    sorted_kwargs = {}
    for i in sorted(kwargs.keys(), key=sorter.get):
        sorted_kwargs[i] = kwargs[i]      
    return sorted_args, sorted_kwargs


def f(a, b, c="hello", d="world"): var = a


print(get_parameters(f))

আউটপুট:

(('a', 'b'), {'c': 'hello', 'd': 'world'})

2

আর্গুমেন্ট নামের একটি তালিকা ফেরত দেয়, পার্টিয়াল এবং নিয়মিত ক্রিয়াকলাপের যত্ন নেয়:

def get_func_args(f):
    if hasattr(f, 'args'):
        return f.args
    else:
        return list(inspect.signature(f).parameters)

2

ব্রায়ানের উত্তরের জন্য আপডেট :

পাইথন 3 এর কোনও ফাংশনে যদি কী-ওয়ার্ড-যুক্তি যুক্তি থাকে, তবে আপনাকে ব্যবহার করতে হবে inspect.getfullargspec:

def yay(a, b=10, *, c=20, d=30):
    pass
inspect.getfullargspec(yay)

এই ফলন:

FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(10,), kwonlyargs=['c', 'd'], kwonlydefaults={'c': 20, 'd': 30}, annotations={})

2

অজগর 3 এ, নীচে তৈরি করা *argsএবং একটিতে **kwargsকরা হয়েছে dict( অর্ডার OrderedDictবজায় রাখতে পাইথন <3.6 ব্যবহার করুন dict):

from functools import wraps

def display_param(func):
    @wraps(func)
    def wrapper(*args, **kwargs):

        param = inspect.signature(func).parameters
        all_param = {
            k: args[n] if n < len(args) else v.default
            for n, (k, v) in enumerate(param.items()) if k != 'kwargs'
        }
        all_param .update(kwargs)
        print(all_param)

        return func(**all_param)
    return wrapper

1

inspect.signatureখুব ধীর। দ্রুততম উপায়

def f(a, b=1, *args, c, d=1, **kwargs):
   pass

f_code = f.__code__
f_code.co_varnames[:f_code.co_argcount + f_code.co_kwonlyargcount]  # ('a', 'b', 'c', 'd')

0

একটি সামান্য বিট আপডেট করতে ব্রায়ান এর উত্তর , সেখানে এখন একটি চমৎকার গুলো পুরনো হয় inspect.signatureপুরনো পাইথন সংস্করণে ব্যবহার করতে পারেন যে: funcsigs। সুতরাং আমার ব্যক্তিগত পছন্দ জন্য যেতে হবে

try:  # python 3.3+
    from inspect import signature
except ImportError:
    from funcsigs import signature

def aMethod(arg1, arg2):
    pass

sig = signature(aMethod)
print(sig)

মজা করার জন্য, যদি আপনি Signatureগতিশীলভাবে অবজেক্টের সাথে খেলতে এবং এলোমেলো স্বাক্ষরগুলির সাথে ফাংশন তৈরি করতে আগ্রহী হন তবে আপনি আমার makefunপ্রকল্পটি দেখতে পারেন।


-3

কি dir()এবং vars()এখন?

খুব সহজেই সুপারকে যা বলা হচ্ছে ঠিক তাই করছে বলে মনে হচ্ছে…

ফাংশন সুযোগের মধ্যে থেকে কল করা আবশ্যক।

তবে সাবধান থাকুন যে এটি সমস্ত স্থানীয় ভেরিয়েবলগুলি ফিরিয়ে দেবে তাই প্রয়োজনে ফাংশনটির একেবারে শুরুতে এটি নিশ্চিত করে নিন।

এছাড়াও মনে রাখবেন যে মন্তব্যগুলিতে উল্লেখ করা হয়েছে, এটি এটিকে সুযোগের বাইরে থেকে করার অনুমতি দেয় না। সুতরাং ঠিক ওপির পরিস্থিতি নয় তবে এখনও প্রশ্নের শিরোনামের সাথে মেলে। সুতরাং আমার উত্তর।


dir () সমস্ত চলক নামেরের তালিকা ['var1', 'var2'], বার্স () অভিধানের রূপটি local 'var1': 0, 'var2': 'কিছু' returns বর্তমান স্থানীয় ক্ষেত্রের মধ্যে থেকে ফিরিয়ে দেয়। কেউ যদি ফাংশনে পরে আর্গুমেন্ট ভেরিয়েবলের নাম ব্যবহার করতে চান, তবে তাদের অন্য একটি স্থানীয় ভেরিয়েবল সংরক্ষণ করা উচিত, কারণ এটি ফাংশনে পরে কল করা যেখানে তারা অন্য স্থানীয় ভেরিয়েবল ঘোষণা করতে পারে এই তালিকাটিকে "দূষিত" করবে। যদি তারা এটিকে ফাংশনের বাইরে ব্যবহার করতে চায় তবে তাদের অবশ্যই কমপক্ষে একবার ফাংশনটি চালাতে হবে এবং এটি বিশ্বব্যাপী পরিবর্তনীয়ভাবে সংরক্ষণ করতে হবে। সুতরাং পরিদর্শন মডিউলটি ব্যবহার করা ভাল।
পিটার মাজকো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.