यदि लक्ष्य आपके कोड में उसी तरह का प्रभाव रखता है जो #ifdef WINDOWS / #endif के पास है .. तो इसे करने का एक तरीका है (मैं मैक btw पर हूँ)।
सिंपल केस, नो चैनिंग
>>> def _ifdef_decorator_impl(plat, func, frame):
... if platform.system() == plat:
... return func
... elif func.__name__ in frame.f_locals:
... return frame.f_locals[func.__name__]
... else:
... def _not_implemented(*args, **kwargs):
... raise NotImplementedError(
... f"Function {func.__name__} is not defined "
... f"for platform {platform.system()}.")
... return _not_implemented
...
...
>>> def windows(func):
... return _ifdef_decorator_impl('Windows', func, sys._getframe().f_back)
...
>>> def macos(func):
... return _ifdef_decorator_impl('Darwin', func, sys._getframe().f_back)
इसलिए इस कार्यान्वयन के साथ आपको वही सिंटैक्स मिलता है जो आपके प्रश्न में है।
>>> @macos
... def zulu():
... print("world")
...
>>> @windows
... def zulu():
... print("hello")
...
>>> zulu()
world
>>>
उपरोक्त कोड क्या कर रहा है, अनिवार्य रूप से, प्लेटफ़ॉर्म से मेल खाने पर ज़ुलु को असाइन कर रहा है। यदि मंच मेल नहीं खाता है, तो यह पहले से परिभाषित होने पर ज़ुलु वापस आ जाएगा। यदि इसे परिभाषित नहीं किया गया था, तो यह एक प्लेसहोल्डर फ़ंक्शन लौटाता है जो एक अपवाद उठाता है।
यदि आप ध्यान में रखते हैं कि डेकोरेटर्स का पता लगाना आसान है
@mydecorator
def foo():
pass
के अनुरूप है:
foo = mydecorator(foo)
यहाँ एक मानकीकृत डेकोरेटर का उपयोग करके एक कार्यान्वयन है:
>>> def ifdef(plat):
... frame = sys._getframe().f_back
... def _ifdef(func):
... return _ifdef_decorator_impl(plat, func, frame)
... return _ifdef
...
>>> @ifdef('Darwin')
... def ice9():
... print("nonsense")
Parameterized सज्जाकार के अनुरूप हैं foo = mydecorator(param)(foo)
।
मैंने उत्तर को थोड़ा अपडेट किया है। टिप्पणियों के जवाब में, मैंने क्लास के तरीकों में आवेदन को शामिल करने और अन्य मॉड्यूल में परिभाषित कार्यों को कवर करने के लिए अपने मूल दायरे का विस्तार किया है। इस अंतिम अपडेट में, मैं यह निर्धारित करने में शामिल जटिलता को कम करने में सक्षम हूं कि क्या एक फ़ंक्शन पहले से ही परिभाषित किया गया है।
[यहाँ एक छोटा सा अद्यतन ... मैं इसे नीचे नहीं डाल सकता - यह एक मजेदार अभ्यास है] मैं इसके बारे में कुछ और परीक्षण कर रहा हूं, और पाया कि यह कॉलबल्स पर आम तौर पर काम करता है - न केवल सामान्य कार्य; आप क्लास के घोषणाओं को भी सजा सकते हैं कि क्या कॉल करने योग्य है या नहीं। और यह कार्यों के आंतरिक कार्यों का समर्थन करता है, इसलिए इस तरह की चीजें संभव हैं (हालांकि शायद अच्छी शैली नहीं है - यह सिर्फ परीक्षण कोड है):
>>> @macos
... class CallableClass:
...
... @macos
... def __call__(self):
... print("CallableClass.__call__() invoked.")
...
... @macos
... def func_with_inner(self):
... print("Defining inner function.")
...
... @macos
... def inner():
... print("Inner function defined for Darwin called.")
...
... @windows
... def inner():
... print("Inner function for Windows called.")
...
... inner()
...
... @macos
... class InnerClass:
...
... @macos
... def inner_class_function(self):
... print("Called inner_class_function() Mac.")
...
... @windows
... def inner_class_function(self):
... print("Called inner_class_function() for windows.")
ऊपर सज्जाकार के बुनियादी तंत्र को दर्शाता है, कैसे कॉल करने वाले के दायरे का उपयोग करना है, और कई सज्जाकारों को कैसे सरल करना है, जिसमें समान कार्य है जिसमें आंतरिक फ़ंक्शन परिभाषित सामान्य एल्गोरिथ्म है।
चैनिंग सपोर्ट
इन सज्जाकारों का पीछा करने का समर्थन करने के लिए यह दर्शाता है कि क्या फ़ंक्शन एक से अधिक प्लेटफ़ॉर्म पर लागू होता है, डेकोरेटर को इस तरह लागू किया जा सकता है:
>>> class IfDefDecoratorPlaceholder:
... def __init__(self, func):
... self.__name__ = func.__name__
... self._func = func
...
... def __call__(self, *args, **kwargs):
... raise NotImplementedError(
... f"Function {self._func.__name__} is not defined for "
... f"platform {platform.system()}.")
...
>>> def _ifdef_decorator_impl(plat, func, frame):
... if platform.system() == plat:
... if type(func) == IfDefDecoratorPlaceholder:
... func = func._func
... frame.f_locals[func.__name__] = func
... return func
... elif func.__name__ in frame.f_locals:
... return frame.f_locals[func.__name__]
... elif type(func) == IfDefDecoratorPlaceholder:
... return func
... else:
... return IfDefDecoratorPlaceholder(func)
...
>>> def linux(func):
... return _ifdef_decorator_impl('Linux', func, sys._getframe().f_back)
इस तरह से आप जंजीरों का समर्थन करते हैं:
>>> @macos
... @linux
... def foo():
... print("works!")
...
>>> foo()
works!
my_callback = windows(<actual function definition>)
- इसलिए नामmy_callback
को ओवरराइट किया जाएगा , भले ही डेकोरेटर क्या कर सकता है। फ़ंक्शन के लिनक्स संस्करण का एकमात्र तरीका उस चर में समाप्त हो सकता है यदिwindows()
इसे वापस कर दिया जाए - लेकिन फ़ंक्शन के पास लिनक्स संस्करण के बारे में जानने का कोई तरीका नहीं है। मुझे लगता है कि इसे पूरा करने का अधिक विशिष्ट तरीका अलग-अलग फ़ाइलों में ओएस-विशिष्ट फ़ंक्शन परिभाषाएं हैं, और सशर्त रूपimport
से उनमें से केवल एक है।