কোনও শ্রেণীর কোনও ফাংশন সংজ্ঞায়িত হয়েছে কিনা তা যাচাই করার দ্রুততম উপায় কী?


132

আমি একটি এআই রাজ্য স্পেস অনুসন্ধান অ্যালগরিদম লিখছি, এবং আমার একটি জেনেরিক বর্গ রয়েছে যা দ্রুত কোনও অনুসন্ধান অ্যালগরিদম বাস্তবায়নের জন্য ব্যবহার করা যেতে পারে। একটি সাবক্লাস প্রয়োজনীয় ক্রিয়াকলাপগুলি সংজ্ঞায়িত করবে, এবং অ্যালগোরিদম বাকী কাজগুলি করবে।

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

def get_operations(self, include_parent=True):
    ops = self._get_operations()
    if not include_parent and self.path.parent_op:
        try:
            parent_inverse = self.invert_op(self.path.parent_op)
            ops.remove(parent_inverse)
        except NotImplementedError:
            pass
    return ops

এবং ইনভার্ট_প ফাংশনটি ডিফল্টরূপে ছুড়ে দেয়।

কোনও ব্যতিক্রম ধরার চেয়ে ফাংশনটি সংজ্ঞায়িত হয়নি কিনা তা দেখার জন্য কি আরও দ্রুত উপায় আছে?

আমি দিরের সাথে উপস্থিত থাকার জন্য পরীক্ষার পাতায় কিছু ভাবছিলাম, তবে এটি ঠিক মনে হচ্ছে না। hasattr getattr কল করে এবং এটি উত্থাপিত হয় কিনা তা যাচাই করে প্রয়োগ করা হয়, যা আমি চাই না।


8
"getattr কল করে এবং এটি উত্থাপিত হয় কিনা তা যাচাই করে hasattr প্রয়োগ করা হয়, যা আমি চাই না" " কেন না? বাস্তবায়ন কী করে আপনি কেন যত্নশীল হন?
স্পষ্টভাবে

4
has_op = lambda obj, op: callable(getattr(obj, op, None))
স্যাম্পেলবায়াস

1
চেষ্টা করুন: hasattr(connection, 'invert_opt')
কেনারব

উত্তর:


204

হ্যাঁ, getattr()বৈশিষ্ট্যটি পেতে ব্যবহার করুন এবং callable()এটি যাচাই করার জন্য একটি পদ্ধতি:

invert_op = getattr(self, "invert_op", None)
if callable(invert_op):
    invert_op(self.path.parent_op)

নোট করুন যে getattr()বৈশিষ্ট্যটি উপস্থিত না থাকলে সাধারণত ব্যতিক্রম ছোঁড়ে। তবে, আপনি যদি কোনও ডিফল্ট মান নির্দিষ্ট করে থাকেন (তবে Noneএই ক্ষেত্রে), এটি পরিবর্তে ফিরে আসবে।


3
এটিও নোট করুন যে getattrএই ক্ষেত্রে বাস্তবায়ন চুপচাপ একটি ব্যতিক্রম ধরা পড়ে এবং পরিবর্তে ডিফল্ট মানটি hasattrদেয়, ঠিক যেমনটি ওপি কিছু কারণে ছিল।
সান্তা

3
যদি ফাংশনটি class শ্রেণিতে না হয় তবে পিতামাতার ক্লাসে থাকে? এক্ষেত্রে আমি একটি সত্যতা পাই, এমনকি বাচ্চারা কখনই সেই ফাংশনটি প্রয়োগ করে না (হ্যাশটার ব্যবহার করে)
অন্ধকার

46

এটি পাইথন 2 এবং পাইথন 3 উভয় ক্ষেত্রেই কাজ করে

hasattr(connection, 'invert_opt')

hasattrTrueসংযোগ অবজেক্টের একটি ফাংশন invert_optসংজ্ঞায়িত করা থাকলে ফেরত দেয় । আপনার চারণ করার জন্য ডকুমেন্টেশন এখানে

https://docs.python.org/2/library/function.html#hasattr https://docs.python.org/3/library/function.html#hasattr


5
যদিও কোডটি প্রশংসা করা হয়েছে, এর সর্বদা একটি সহিত ব্যাখ্যা থাকা উচিত। এটি দীর্ঘ হতে হবে না তবে এটি প্রত্যাশিত।
পিটারহ - মনিকা

ভাল, আপনি কোনও নিবন্ধের দিকে ইঙ্গিত করতে পারেন যদিও তাতে কোনও ক্ষতি হবে না :)
ভিটালিয়ায় তেরজিভ

5
যদি সংযোগের কোনও বৈশিষ্ট্য থাকে তবে এটি সত্যও ফেরায় connection.invert_opt = 'foo'
রবার্ট হ্যানিগ

20

কোনও ব্যতিক্রম ধরার চেয়ে ফাংশনটি সংজ্ঞায়িত হয়নি কিনা তা দেখার জন্য কি আরও দ্রুত উপায় আছে?

কেন আপনি এর বিরুদ্ধে? বেশিরভাগ পাইথোনিক ক্ষেত্রে অনুমতি চেয়ে ক্ষমা চাওয়া ভাল। ;-)

hasattr getattr কল করে এবং এটি উত্থাপিত হয় কিনা তা যাচাই করে প্রয়োগ করা হয়, যা আমি চাই না।

আবার, কেন? নিম্নলিখিতটি বেশ পাইথোনিক:

    try:
        invert_op = self.invert_op
    except AttributeError:
        pass
    else:
        parent_inverse = invert_op(self.path.parent_op)
        ops.remove(parent_inverse)

অথবা,

    # if you supply the optional `default` parameter, no exception is thrown
    invert_op = getattr(self, 'invert_op', None)  
    if invert_op is not None:
        parent_inverse = invert_op(self.path.parent_op)
        ops.remove(parent_inverse)

নোট, তবে, এটি getattr(obj, attr, default)মূলত খুব ব্যতিক্রম ধরা দ্বারা প্রয়োগ করা হয়। পাইথনের জমিতে কিছু নেই!


4

প্রতিক্রিয়াগুলি এখানে স্ট্রিংকে অবজেক্টের কোনও গুণকের নাম কিনা তা যাচাই করে। বৈশিষ্ট্যটি কোনও পদ্ধতি কিনা তা পরীক্ষা করার জন্য একটি অতিরিক্ত পদক্ষেপ (কলযোগ্য ব্যবহার করে) প্রয়োজন।

সুতরাং এটি এটিকে সিদ্ধ করে দেয়: কোনও বস্তুর আপত্তিটির কোনও বৈশিষ্ট্যযুক্তি আছে কিনা তা যাচাই করার দ্রুততম উপায় কী। উত্তরটা হচ্ছে

'attrib' in obj.__dict__

এটি তাই কারণ কোনও ডিক তার চাবিগুলি হ্যাশ করে তাই কীটির অস্তিত্বের জন্য পরীক্ষা করা দ্রুত is

নীচে সময় তুলনা দেখুন।

>>> class SomeClass():
...         pass
...
>>> obj = SomeClass()
>>>
>>> getattr(obj, "invert_op", None)
>>>
>>> %timeit getattr(obj, "invert_op", None)
1000000 loops, best of 3: 723 ns per loop
>>> %timeit hasattr(obj, "invert_op")
The slowest run took 4.60 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 674 ns per loop
>>> %timeit "invert_op" in obj.__dict__
The slowest run took 12.19 times longer than the fastest. This could mean that an intermediate result is being cached.
10000000 loops, best of 3: 176 ns per loop

এটি ব্যবহৃত ক্লাসগুলিতে ব্যর্থ __slots____slots__ute 10% দ্বারা অ্যাট্রিবিউট অ্যাক্সেস গতিতে সহায়তা করুন। stackoverflow.com/a/14119024/1459669
noɥʇʎԀʎzɐɹƆ

3

আমি নাথন অস্টগার্ডের উত্তর পছন্দ করি এবং আমি এটির পক্ষে ভোট দিয়েছি। তবে আপনি নিজের সমস্যার সমাধানের অন্য উপায়টি হ'ল একটি মেমোজাইজ ডেকরেটার ব্যবহার করুন যা ফাংশন কলটির ফলাফলকে ক্যাশে করবে। সুতরাং আপনি এগিয়ে যেতে পারেন এবং একটি ব্যয়বহুল ফাংশন রাখতে পারেন যা কিছু খুঁজে বের করে, তবে তারপরে আপনি যখন এটি কল করেন এবং পরবর্তী কলগুলি দ্রুত হয়; ফাংশনের স্মৃতিযুক্ত সংস্করণটি ডিকটিতে আর্গুমেন্টগুলি সন্ধান করে, আসল ফাংশনটি ফলাফলটি গণনা করার সময় থেকে ডকের ফলাফল খুঁজে পায় এবং ফলস্বরূপ ফলাফল প্রদান করে।

এখানে রেমন্ড হেট্টিংগার "lru_cache" নামে একটি স্মরণীয় সাজসজ্জার জন্য একটি রেসিপি দেওয়া হয়েছে। পাইথন ৩.২-এর ফান্টুলস মডিউলে এটির একটি সংস্করণ এখন স্ট্যান্ডার্ড।

http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/

http://docs.python.org/release/3.2/library/functools.html


2

পাইথনের যে কোনও কিছুর মতো, যদি আপনি যথেষ্ট চেষ্টা করেন তবে আপনি সাহসী হয়ে পেতে পারেন এবং সত্যিই বাজে কিছু করতে পারেন। এখন, এই বাজে অংশটি:

def invert_op(self, op):
    raise NotImplementedError

def is_invert_op_implemented(self):
    # Only works in CPython 2.x of course
    return self.invert_op.__code__.co_code == 't\x00\x00\x82\x01\x00d\x00\x00S'

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


পদ্ধতিটি যদি কোনও ব্যতিক্রম উত্থাপন করে তবে এটি সত্য হবে। co_namesসমান কিনা তাও পরীক্ষা করে দেখা উচিত ('NotImplementedError',)। তবে আমি নিশ্চিত নই যে এটি কম-বেশি খারাপ করে তোলে কিনা।
পাঠান

1

আপনি ক্লাসেও যেতে পারেন:

import inspect


def get_methods(cls_):
    methods = inspect.getmembers(cls_, inspect.isfunction)
    return dict(methods)

# Example
class A(object):
    pass

class B(object):
    def foo():
        print('B')


# If you only have an object, you can use `cls_ = obj.__class__`
if 'foo' in get_methods(A):
    print('A has foo')

if 'foo' in get_methods(B):
    print('B has foo')

0

__ডিক্ট__ সম্পত্তিতে বৈশিষ্ট্যগুলি পরীক্ষা করা সত্যিই দ্রুত, আপনি এটি পদ্ধতিগুলির জন্য ব্যবহার করতে পারবেন না, যেহেতু তারা __ডিক্ট__ হ্যাশগুলিতে উপস্থিত হয় না। পারফরম্যান্সটি যদি গুরুত্বপূর্ণ হয় তবে আপনি আপনার ক্লাসে হ্যাকিংয়ের আশ্রয় নিতে পারেন:

class Test():
    def __init__():
        # redefine your method as attribute
        self.custom_method = self.custom_method

    def custom_method(self):
        pass

তারপরে পদ্ধতিটি যাচাই করুন:

t = Test()
'custom_method' in t.__dict__

সময়ের সাথে তুলনা getattr:

>>%timeit 'custom_method' in t.__dict__
55.9 ns ± 0.626 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

>>%timeit getattr(t, 'custom_method', None)
116 ns ± 0.765 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

এমন নয় যে আমি এই পদ্ধতিকে উত্সাহ দিচ্ছি, তবে এটি কার্যকর বলে মনে হচ্ছে।

[সম্পাদনা] যখন পদ্ধতির নাম প্রদত্ত শ্রেণিতে না হয় তখন পারফরম্যান্স বুস্ট আরও বেশি হয়:

>>%timeit 'rubbish' in t.__dict__
65.5 ns ± 11 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

>>%timeit getattr(t, 'rubbish', None)
385 ns ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

1
__dict__ওভাররাইড করা যেতে পারে। এটি বিশ্বাস করা যায় না।
জিয়াও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.