উত্তর:
পাইথনে, ফাংশন এবং আবদ্ধ পদ্ধতির মধ্যে পার্থক্য রয়েছে।
>>> def foo():
... print "foo"
...
>>> class A:
... def bar( self ):
... print "bar"
...
>>> a = A()
>>> foo
<function foo at 0x00A98D70>
>>> a.bar
<bound method A.bar of <__main__.A instance at 0x00A9BC88>>
>>>
বাউন্ড পদ্ধতিগুলি একটি উদাহরণের জন্য "আবদ্ধ" (কীভাবে বর্ণনামূলক) হয়েছে এবং পদ্ধতিটি যখনই ডাকা হয় তখনই সেই দণ্ডটি প্রথম আর্গুমেন্ট হিসাবে পাস করা হবে।
শ্রেণীর বৈশিষ্ট্যযুক্ত কলযোগ্য (উদাহরণের বিপরীতে) এখনও আনবাউন্ড নয়, তাই আপনি যখনই চান শ্রেণীর সংজ্ঞাটি সংশোধন করতে পারবেন:
>>> def fooFighters( self ):
... print "fooFighters"
...
>>> A.fooFighters = fooFighters
>>> a2 = A()
>>> a2.fooFighters
<bound method A.fooFighters of <__main__.A instance at 0x00A9BEB8>>
>>> a2.fooFighters()
fooFighters
পূর্বে সংজ্ঞায়িত দৃষ্টান্তগুলি পাশাপাশি আপডেট করা হয় (যতক্ষণ না তারা নিজেরাই এ্যাট্রিবিউটটি বাদ দিয়ে দেয় না):
>>> a.fooFighters()
fooFighters
সমস্যাটি তখনই আসে যখন আপনি একটি পদ্ধতিটি একটি একক দৃষ্টিতে সংযুক্ত করতে চান:
>>> def barFighters( self ):
... print "barFighters"
...
>>> a.barFighters = barFighters
>>> a.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: barFighters() takes exactly 1 argument (0 given)
ফাংশনটি স্বয়ংক্রিয়ভাবে আবদ্ধ হয় না যখন এটি কোনও উদাহরণের সাথে সরাসরি সংযুক্ত থাকে:
>>> a.barFighters
<function barFighters at 0x00A98EF0>
এটি আবদ্ধ করতে, আমরা প্রকার মডিউলটিতে মেথডটাইপ ফাংশনটি ব্যবহার করতে পারি :
>>> import types
>>> a.barFighters = types.MethodType( barFighters, a )
>>> a.barFighters
<bound method ?.barFighters of <__main__.A instance at 0x00A9BC88>>
>>> a.barFighters()
barFighters
এবার শ্রেণীর অন্যান্য দৃষ্টান্ত প্রভাবিত হয়নি:
>>> a2.barFighters()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'barFighters'
বর্ণনাকারী এবং মেটাক্লাস প্রোগ্রামিং সম্পর্কে পড়ার মাধ্যমে আরও তথ্য পাওয়া যাবে ।
descriptor protocol
বনাম ব্যবহারের কোনও সুবিধা MethodType
সম্ভবত কিছুটা বেশি পঠনযোগ্য হতে পারে a
classmethod
এবং staticmethod
এবং অন্যান্য বর্ণনাকারী খুব। এটি আর একটি আমদানির সাথে নেমস্পেসকে বিশৃঙ্খলা এড়ায়।
a.barFighters = barFighters.__get__(a)
অজগর ২.6 থেকে মডিউল নতুন অবহিত এবং 3.0 এ সরানো হয়েছে, প্রকারগুলি ব্যবহার করুন
দেখতে http://docs.python.org/library/new.html
নীচের উদাহরণে আমি patch_me()
ফাংশন থেকে ইচ্ছাকৃতভাবে রিটার্ন মান সরিয়েছি । আমি মনে করি যে রিটার্ন মান দেওয়ার ফলে একজনকে বিশ্বাস করা যায় যে প্যাচটি একটি নতুন অবজেক্ট ফিরিয়ে দেয়, যা সত্য নয় - এটি আগতটিকে সংশোধন করে। সম্ভবত এটি বানকিপ্যাচিংয়ের আরও সুশৃঙ্খল ব্যবহারের সুবিধার্থ করতে পারে।
import types
class A(object):#but seems to work for old style objects too
pass
def patch_me(target):
def method(target,x):
print "x=",x
print "called from", target
target.method = types.MethodType(method,target)
#add more if needed
a = A()
print a
#out: <__main__.A object at 0x2b73ac88bfd0>
patch_me(a) #patch instance
a.method(5)
#out: x= 5
#out: called from <__main__.A object at 0x2b73ac88bfd0>
patch_me(A)
A.method(6) #can patch class too
#out: x= 6
#out: called from <class '__main__.A'>
উপস্থাপনা - সামঞ্জস্যের উপর একটি নোট: অন্যান্য উত্তরগুলি কেবল পাইথন 2 এ কাজ করতে পারে - এই উত্তরটি পাইথন 2 এবং 3 এ পুরোপুরি ভালভাবে কাজ করা উচিত যদি কেবল পাইথন 3 লিখতে পারেন তবে আপনি স্পষ্টতই উত্তরাধিকার সূত্রে ছেড়ে যেতে পারেন object
, তবে অন্যথায় কোডটি একই থাকবে should ।
একটি বিদ্যমান অবজেক্ট ইনস্ট্যান্সে একটি পদ্ধতি যুক্ত করা
আমি পড়েছি যে পাইথনের কোনও বিদ্যমান অবজেক্টে (উদাহরণস্বরূপ শ্রেণির সংজ্ঞায় নয়) একটি পদ্ধতি যুক্ত করা সম্ভব।
আমি বুঝতে পারি যে এটি করা সবসময় ভাল সিদ্ধান্ত নয়। কিন্তু, কেউ কীভাবে এটি করতে পারে?
আমি এটি সুপারিশ করি না। এটি একটি খারাপ ধারণা। এটা করবেন না।
এখানে বেশ কয়েকটি কারণ রয়েছে:
সুতরাং, আমি আপনাকে পরামর্শ দিচ্ছি যে যদি আপনি সত্যিকারের কোনও ভাল কারণ না পান তবে আপনি এটি করবেন না। এটা তোলে অনেক ভালো বর্গ সংজ্ঞা সঠিক পদ্ধতি নির্ধারণ করতে হয় বা কম ভালো, বানর-প্যাচ থেকে বাঞ্ছনীয় বর্গ সরাসরি:
Foo.sample_method = sample_method
যেহেতু এটি শিক্ষণীয়, তবে আমি আপনাকে এটি করার কিছু উপায় দেখাব।
এখানে কিছু সেটআপ কোড। আমাদের ক্লাস সংজ্ঞা দরকার। এটি আমদানি করা যেতে পারে, তবে এটি সত্যিই কিছু যায় আসে না।
class Foo(object):
'''An empty class to demonstrate adding a method to an instance'''
একটি উদাহরণ তৈরি করুন:
foo = Foo()
এটিতে যুক্ত করার জন্য একটি পদ্ধতি তৈরি করুন:
def sample_method(self, bar, baz):
print(bar + baz)
__get__
ফাংশনগুলিতে বিন্দুযুক্ত __get__
দৃষ্টিকোণগুলি ফাংশনটির পদ্ধতিটিকে দৃষ্টান্তের সাথে কল করে , বস্তুকে পদ্ধতির সাথে আবদ্ধ করে এবং এইভাবে একটি "আবদ্ধ পদ্ধতি" তৈরি করে।
foo.sample_method = sample_method.__get__(foo)
এবং এখন:
>>> foo.sample_method(1,2)
3
প্রথমত, আমদানির প্রকারগুলি, যেখান থেকে আমরা পদ্ধতিটি নির্মাণকারী পেয়ে যাব:
import types
এখন আমরা উদাহরণটি পদ্ধতিতে যুক্ত করব। এটি করার জন্য, আমাদের types
মডিউলটি (যা আমরা উপরে আমদানি করেছি) থেকে মেথডটাইপ নির্মাণকারী প্রয়োজন ।
প্রকারের জন্য আর্গুমেন্ট স্বাক্ষর eth মেথডটাইপটি হ'ল (function, instance, class)
:
foo.sample_method = types.MethodType(sample_method, foo, Foo)
এবং ব্যবহার:
>>> foo.sample_method(1,2)
3
প্রথমত, আমরা একটি মোড়ক ফাংশন তৈরি করি যা পদ্ধতিটিকে উদাহরণের সাথে আবদ্ধ করে:
def bind(instance, method):
def binding_scope_fn(*args, **kwargs):
return method(instance, *args, **kwargs)
return binding_scope_fn
ব্যবহার:
>>> foo.sample_method = bind(foo, sample_method)
>>> foo.sample_method(1,2)
3
একটি আংশিক ফাংশন কোনও ফাংশনে প্রথম যুক্তি (গুলি) প্রয়োগ করে (এবং allyচ্ছিকভাবে কীওয়ার্ড আর্গুমেন্টগুলি), এবং পরে অবশিষ্ট আর্গুমেন্টগুলি (এবং কীওয়ার্ড আর্গুমেন্টকে ওভাররাইডিং) দিয়ে ডাকা যেতে পারে। এভাবে:
>>> from functools import partial
>>> foo.sample_method = partial(sample_method, foo)
>>> foo.sample_method(1,2)
3
আপনি যখন বিবেচনা করেন যে আবদ্ধ পদ্ধতিগুলি উদাহরণের আংশিক ফাংশন are
আমরা যদি ক্লাসে এটি যোগ করতে পারে সেভাবে নমুনা_ thodতিহ্যকে যুক্ত করার চেষ্টা করি, এটি উদাহরণ থেকে অবিরাম, এবং অন্তর্নিহিত স্বটিকে প্রথম যুক্তি হিসাবে গ্রহণ করে না।
>>> foo.sample_method = sample_method
>>> foo.sample_method(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sample_method() takes exactly 3 arguments (2 given)
আমরা আনবাউন্ড ফাংশনটি স্পষ্টভাবে উদাহরণটি (বা যেহেতু যে কোনও পদ্ধতিতে আসলে self
আর্গুমেন্ট ভেরিয়েবল ব্যবহার করে না ) পাস করে কাজটি করতে পারি , তবে এটি অন্যান্য উদাহরণগুলির প্রত্যাশিত স্বাক্ষরের সাথে সামঞ্জস্যপূর্ণ হবে না (যদি আমরা বানর-প্যাচিং করছি) এই উদাহরণ):
>>> foo.sample_method(foo, 1, 2)
3
আপনি এখন বেশ কয়েকটি উপায়ে জানেন যে আপনি এটি করতে পারেন তবে সমস্ত গম্ভীরতার সাথে - এটি করবেন না।
__get__
পদ্ধতি পরবর্তী প্যারামিটার হিসাবে বর্গ দরকার: sample_method.__get__(foo, Foo)
।
আমি মনে করি যে উপরের উত্তরগুলি মূল পয়েন্টটি মিস করেছে।
একটি পদ্ধতি সহ একটি ক্লাস করা যাক:
class A(object):
def m(self):
pass
এখন, আইপিথনে এটি নিয়ে খেলি:
In [2]: A.m
Out[2]: <unbound method A.m>
ঠিক আছে, তাই মি () একরকম একজন আনবাউন্ড পদ্ধতি হয়ে একজন । তবে আসলেই কি এরকম?
In [5]: A.__dict__['m']
Out[5]: <function m at 0xa66b8b4>
দেখা যাচ্ছে যে এম () কেবল একটি ফাংশন, রেফারেন্স যা একটি শ্রেণীর অভিধানে যুক্ত করা হয়েছে - কোনও জাদু নেই। তাহলে কেন অ্যাম আমাদের একটি বাধাহীন পদ্ধতি দেয়? এটি কারণ একটি সাধারণ অভিধান অনুসন্ধানে বিন্দু অনুবাদ করা হয়নি। এটি আসলে A .__ শ্রেণির কল __.__ getattribute __ (এ, 'মি'):
In [11]: class MetaA(type):
....: def __getattribute__(self, attr_name):
....: print str(self), '-', attr_name
In [12]: class A(object):
....: __metaclass__ = MetaA
In [23]: A.m
<class '__main__.A'> - m
<class '__main__.A'> - m
এখন, আমি নিশ্চিত নই যে আমার মাথার উপরের অংশটি কেন শেষ পংক্তিটি দু'বার মুদ্রিত হয়েছে, তবে এখনও সেখানে কী চলছে তা পরিষ্কার।
এখন, ডিফল্ট __getattribute__ কী করে এটি এটি পরীক্ষা করে যে বৈশিষ্ট্যটি তথাকথিত বর্ণনাকারী কিনা, অর্থাৎ এটি যদি একটি বিশেষ __get__ পদ্ধতি প্রয়োগ করে। যদি এটি সেই পদ্ধতিটি কার্যকর করে, তবে যা ফিরে আসে তা __get__ পদ্ধতি কল করার ফলাফল of আমাদের এ ক্লাসের প্রথম সংস্করণে ফিরে যাওয়া , এটি আমাদের কাছে রয়েছে:
In [28]: A.__dict__['m'].__get__(None, A)
Out[28]: <unbound method A.m>
এবং পাইথন ফাংশনগুলি ডেস্ক্রিপ্টর প্রোটোকল বাস্তবায়িত করে, যদি তাদের কোনও বস্তুর পক্ষে ডাকা হয়, তারা তাদের __get__ পদ্ধতিতে সেই বস্তুর সাথে আবদ্ধ হয়।
ঠিক আছে, সুতরাং একটি বিদ্যমান অবজেক্টে কীভাবে একটি পদ্ধতি যুক্ত করবেন? ধরে নিই যে আপনার প্যাচিং ক্লাসটি আপত্তি নেই, এটি এতটা সহজ:
B.m = m
তারপরে বিএম "আনবাউন্ড পদ্ধতি" হয়ে যায়, বর্ণনাকারী যাদুটির জন্য ধন্যবাদ।
এবং যদি আপনি কোনও একক বস্তুতে কোনও পদ্ধতি যুক্ত করতে চান, তবে আপনাকে নিজেই প্রকারগুলি ব্যবহার করে যন্ত্রপাতিটি অনুকরণ করতে হবে ethমেথডটাইপ:
b.m = types.MethodType(m, b)
যাইহোক:
In [2]: A.m
Out[2]: <unbound method A.m>
In [59]: type(A.m)
Out[59]: <type 'instancemethod'>
In [60]: type(b.m)
Out[60]: <type 'instancemethod'>
In [61]: types.MethodType
Out[61]: <type 'instancemethod'>
পাইথনে বানর প্যাচিং সাধারণত কোনও শ্রেণি ওভাররাইট করে আপনার নিজের সাথে স্বাক্ষর ফাংশন করে works নীচে জোপ উইকির একটি উদাহরণ দেওয়া হল :
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
এই কোডটি ক্লাসে স্পোক নামক একটি পদ্ধতি ওভাররাইট / তৈরি করবে। বানর প্যাচিংয়ের বিষয়ে জেফ আতউডের সাম্প্রতিক পোস্টে । তিনি সি # 3.0 এ একটি উদাহরণ দেখান যা আমি কাজের জন্য বর্তমান ভাষা ব্যবহার করি।
আপনি কোনও পদ্ধতির সাথে আবদ্ধ হতে লাম্বদা ব্যবহার করতে পারেন:
def run(self):
print self._instanceString
class A(object):
def __init__(self):
self._instanceString = "This is instance string"
a = A()
a.run = lambda: run(a)
a.run()
আউটপুট:
This is instance string
উদাহরণ ছাড়াই কোনও পদ্ধতি সংযুক্ত করার জন্য কমপক্ষে দুটি উপায় রয়েছে types.MethodType
:
>>> class A:
... def m(self):
... print 'im m, invoked with: ', self
>>> a = A()
>>> a.m()
im m, invoked with: <__main__.A instance at 0x973ec6c>
>>> a.m
<bound method A.m of <__main__.A instance at 0x973ec6c>>
>>>
>>> def foo(firstargument):
... print 'im foo, invoked with: ', firstargument
>>> foo
<function foo at 0x978548c>
1:
>>> a.foo = foo.__get__(a, A) # or foo.__get__(a, type(a))
>>> a.foo()
im foo, invoked with: <__main__.A instance at 0x973ec6c>
>>> a.foo
<bound method A.foo of <__main__.A instance at 0x973ec6c>>
2:
>>> instancemethod = type(A.m)
>>> instancemethod
<type 'instancemethod'>
>>> a.foo2 = instancemethod(foo, a, type(a))
>>> a.foo2()
im foo, invoked with: <__main__.A instance at 0x973ec6c>
>>> a.foo2
<bound method instance.foo of <__main__.A instance at 0x973ec6c>>
দরকারী লিঙ্কগুলি:
ডেটা মডেল - বর্ণনাকারী বর্ণনাকারী
ডেস্ক্রিপ্টর হাওটো গাইড - ইনোভাকিং ডিসক্রিপটর
আপনি যা খুঁজছেন তা setattr
আমি বিশ্বাস করি। কোনও অবজেক্টে একটি অ্যাট্রিবিউট সেট করতে এটি ব্যবহার করুন।
>>> def printme(s): print repr(s)
>>> class A: pass
>>> setattr(A,'printme',printme)
>>> a = A()
>>> a.printme() # s becomes the implicit 'self' variable
< __ main __ . A instance at 0xABCDEFG>
A
, উদাহরণটি নয় a
।
setattr(A,'printme',printme)
পরিবর্তে ব্যবহার করার কোনও কারণ আছে কি A.printme = printme
?
যেহেতু এই প্রশ্নটি পাইথনবিহীন সংস্করণগুলির জন্য জিজ্ঞাসা করেছে, তাই এখানে জাভাস্ক্রিপ্ট রয়েছে:
a.methodname = function () { console.log("Yay, a new method!") }
জেসন প্র্যাট এবং সম্প্রদায় উইকি উত্তরগুলি একত্রিত করে বাইন্ডিংয়ের বিভিন্ন পদ্ধতির ফলাফলগুলি দেখুন:
বিশেষত নোট করুন কীভাবে বন্ডিং ফাংশনটি ক্লাসের পদ্ধতি হিসাবে যুক্ত করে তা কার্যকর করে তবে রেফারেন্সিং সুযোগটি ভুল।
#!/usr/bin/python -u
import types
import inspect
## dynamically adding methods to a unique instance of a class
# get a list of a class's method type attributes
def listattr(c):
for m in [(n, v) for n, v in inspect.getmembers(c, inspect.ismethod) if isinstance(v,types.MethodType)]:
print m[0], m[1]
# externally bind a function as a method of an instance of a class
def ADDMETHOD(c, method, name):
c.__dict__[name] = types.MethodType(method, c)
class C():
r = 10 # class attribute variable to test bound scope
def __init__(self):
pass
#internally bind a function as a method of self's class -- note that this one has issues!
def addmethod(self, method, name):
self.__dict__[name] = types.MethodType( method, self.__class__ )
# predfined function to compare with
def f0(self, x):
print 'f0\tx = %d\tr = %d' % ( x, self.r)
a = C() # created before modified instnace
b = C() # modified instnace
def f1(self, x): # bind internally
print 'f1\tx = %d\tr = %d' % ( x, self.r )
def f2( self, x): # add to class instance's .__dict__ as method type
print 'f2\tx = %d\tr = %d' % ( x, self.r )
def f3( self, x): # assign to class as method type
print 'f3\tx = %d\tr = %d' % ( x, self.r )
def f4( self, x): # add to class instance's .__dict__ using a general function
print 'f4\tx = %d\tr = %d' % ( x, self.r )
b.addmethod(f1, 'f1')
b.__dict__['f2'] = types.MethodType( f2, b)
b.f3 = types.MethodType( f3, b)
ADDMETHOD(b, f4, 'f4')
b.f0(0) # OUT: f0 x = 0 r = 10
b.f1(1) # OUT: f1 x = 1 r = 10
b.f2(2) # OUT: f2 x = 2 r = 10
b.f3(3) # OUT: f3 x = 3 r = 10
b.f4(4) # OUT: f4 x = 4 r = 10
k = 2
print 'changing b.r from {0} to {1}'.format(b.r, k)
b.r = k
print 'new b.r = {0}'.format(b.r)
b.f0(0) # OUT: f0 x = 0 r = 2
b.f1(1) # OUT: f1 x = 1 r = 10 !!!!!!!!!
b.f2(2) # OUT: f2 x = 2 r = 2
b.f3(3) # OUT: f3 x = 3 r = 2
b.f4(4) # OUT: f4 x = 4 r = 2
c = C() # created after modifying instance
# let's have a look at each instance's method type attributes
print '\nattributes of a:'
listattr(a)
# OUT:
# attributes of a:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FD88>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FD88>>
# f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FD88>>
print '\nattributes of b:'
listattr(b)
# OUT:
# attributes of b:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x000000000230FE08>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x000000000230FE08>>
# f0 <bound method C.f0 of <__main__.C instance at 0x000000000230FE08>>
# f1 <bound method ?.f1 of <class __main__.C at 0x000000000237AB28>>
# f2 <bound method ?.f2 of <__main__.C instance at 0x000000000230FE08>>
# f3 <bound method ?.f3 of <__main__.C instance at 0x000000000230FE08>>
# f4 <bound method ?.f4 of <__main__.C instance at 0x000000000230FE08>>
print '\nattributes of c:'
listattr(c)
# OUT:
# attributes of c:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002313108>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002313108>>
# f0 <bound method C.f0 of <__main__.C instance at 0x0000000002313108>>
ব্যক্তিগতভাবে, আমি বাহ্যিক ADDMETHOD ফাংশন রুটটিকে পছন্দ করি, কারণ এটি আমাকে गतिগতভাবে একটি পুনরুক্তরের মধ্যেও নতুন পদ্ধতির নাম নির্ধারণ করতে দেয়।
def y(self, x):
pass
d = C()
for i in range(1,5):
ADDMETHOD(d, y, 'f%d' % i)
print '\nattributes of d:'
listattr(d)
# OUT:
# attributes of d:
# __init__ <bound method C.__init__ of <__main__.C instance at 0x0000000002303508>>
# addmethod <bound method C.addmethod of <__main__.C instance at 0x0000000002303508>>
# f0 <bound method C.f0 of <__main__.C instance at 0x0000000002303508>>
# f1 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f2 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f3 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
# f4 <bound method ?.y of <__main__.C instance at 0x0000000002303508>>
addmethod
নিম্নলিখিত উপায়ে পুনরায় লিখিত def addmethod(self, method, name): self.__dict__[name] = types.MethodType( method, self )
সমস্যা সমাধান করে
যদিও জেসনস উত্তরটি কাজ করে, এটি কেবল তখনই কাজ করে যদি কেউ কোনও ক্লাসে কোনও ফাংশন যুক্ত করতে চায়। আমি .py উত্স কোড ফাইল থেকে ইতিমধ্যে বিদ্যমান পদ্ধতিটি পুনরায় লোড করার চেষ্টা করার সময় এটি আমার পক্ষে কার্যকর হয়নি।
যুগে যুগে কাজটি খুঁজে পেতে আমার পক্ষে সময় লাগল, তবে কৌশলটি সহজ বলে মনে হচ্ছে ... 1. প্রথম উত্স কোড ফাইল থেকে কোডটি আমদানি করুন 2. এবং পুনরায় লোড করার জন্য বাধ্য করুন 3..rd ব্যবহার করুন.আর ফাংশনটাইপ (...) রূপান্তর করতে কোনও ফাংশনে আমদানিকৃত এবং আবদ্ধ পদ্ধতি আপনি বর্তমান বৈশ্বিক চলকগুলিতেও পাস করতে পারেন, কারণ পুনরায় লোড করা পদ্ধতিটি ভিন্ন নাম স্পেসের ৪ র্থ হতে পারে এখন আপনি টাইপস.মেথডটাইপ ব্যবহার করে "জেসন প্র্যাট" পরামর্শ অনুসারে চালিয়ে যেতে পারেন (... )
উদাহরণ:
# this class resides inside ReloadCodeDemo.py
class A:
def bar( self ):
print "bar1"
def reloadCode(self, methodName):
''' use this function to reload any function of class A'''
import types
import ReloadCodeDemo as ReloadMod # import the code as module
reload (ReloadMod) # force a reload of the module
myM = getattr(ReloadMod.A,methodName) #get reloaded Method
myTempFunc = types.FunctionType(# convert the method to a simple function
myM.im_func.func_code, #the methods code
globals(), # globals to use
argdefs=myM.im_func.func_defaults # default values for variables if any
)
myNewM = types.MethodType(myTempFunc,self,self.__class__) #convert the function to a method
setattr(self,methodName,myNewM) # add the method to the function
if __name__ == '__main__':
a = A()
a.bar()
# now change your code and save the file
a.reloadCode('bar') # reloads the file
a.bar() # now executes the reloaded code
যদি এটি কোনও উপকারে আসতে পারে তবে বানর প্যাচিংয়ের প্রক্রিয়াটিকে আরও সুবিধাজনক করার জন্য আমি সম্প্রতি গরিলা নামে একটি পাইথন গ্রন্থাগার প্রকাশ করেছি।
needle()
নামের একটি মডিউলটি প্যাচ করার জন্য একটি ফাংশন ব্যবহার guineapig
করা নিম্নরূপ:
import gorilla
import guineapig
@gorilla.patch(guineapig)
def needle():
print("awesome")
তবে এটি ডকুমেন্টেশন থেকে এফএকিউতে দেখানো হিসাবে আরও আকর্ষণীয় ব্যবহারের ক্ষেত্রেও যত্ন নেয় ।
কোডটি গিটহাবটিতে উপলব্ধ ।
এই প্রশ্নটি বেশ কয়েক বছর আগে খোলা হয়েছিল, তবে ওহে, সাজসজ্জার ব্যবহার করে কোনও শ্রেণীর উদাহরণের সাথে কোনও ফাংশনের বাঁধাই অনুকরণ করার সহজ উপায় রয়েছে:
def binder (function, instance):
copy_of_function = type (function) (function.func_code, {})
copy_of_function.__bind_to__ = instance
def bound_function (*args, **kwargs):
return copy_of_function (copy_of_function.__bind_to__, *args, **kwargs)
return bound_function
class SupaClass (object):
def __init__ (self):
self.supaAttribute = 42
def new_method (self):
print self.supaAttribute
supaInstance = SupaClass ()
supaInstance.supMethod = binder (new_method, supaInstance)
otherInstance = SupaClass ()
otherInstance.supaAttribute = 72
otherInstance.supMethod = binder (new_method, otherInstance)
otherInstance.supMethod ()
supaInstance.supMethod ()
সেখানে, যখন আপনি ফাংশনটি এবং দৃষ্টান্তটি বাইদার সজ্জাটির কাছে পাস করবেন, এটি একটি নতুন ফাংশন তৈরি করবে, প্রথমটির মতো একই কোড অবজেক্টের সাথে। তারপরে, শ্রেণীর প্রদত্ত উদাহরণ সদ্য নির্মিত ফাংশনের একটি বৈশিষ্ট্যে সংরক্ষণ করা হয়। সাজসজ্জারটি স্বয়ংক্রিয়ভাবে অনুলিপি করা একটি (তৃতীয়) ফাংশনটি অনুলিপি করে প্রথম পরামিতি হিসাবে উদাহরণ দেয়।
উপসংহারে আপনি একটি ফাংশন অনুকরণ করে যা এটি শ্রেণীর উদাহরণের সাথে বাধ্যতামূলক। আসল ফাংশনটি অপরিবর্তিত রাখা।
জেসন প্র্যাট যা পোস্ট করেছেন তা সঠিক।
>>> class Test(object):
... def a(self):
... pass
...
>>> def b(self):
... pass
...
>>> Test.b = b
>>> type(b)
<type 'function'>
>>> type(Test.a)
<type 'instancemethod'>
>>> type(Test.b)
<type 'instancemethod'>
যেমন আপনি দেখতে পাচ্ছেন, পাইথন খ () এর চেয়ে বি () এর চেয়ে আলাদা কিছু বিবেচনা করে না। পাইথনে সমস্ত পদ্ধতি কেবল ভেরিয়েবল যা ফাংশন হিসাবে ঘটে।
Test
, এর উদাহরণ নয়।
আমি এটি আশ্চর্যজনক মনে করি যে কেউ উল্লিখিত হয়নি যে উপরে তালিকাভুক্ত সমস্ত পদ্ধতি যুক্ত পদ্ধতি এবং উদাহরণের মধ্যে একটি চক্র রেফারেন্স তৈরি করে, যার ফলে আবর্জনা সংগ্রহের সময় অবধি অবিরত থাকবে। অবজেক্টটির শ্রেণি বাড়িয়ে একটি বর্ণনাকারী যুক্ত করার একটি পুরানো কৌশল ছিল:
def addmethod(obj, name, func):
klass = obj.__class__
subclass = type(klass.__name__, (klass,), {})
setattr(subclass, name, func)
obj.__class__ = subclass
from types import MethodType
def method(self):
print 'hi!'
setattr( targetObj, method.__name__, MethodType(method, targetObj, type(method)) )
এটির সাহায্যে আপনি স্ব পয়েন্টারটি ব্যবহার করতে পারেন
MethodType
, ডেস্ক্রিপ্টর প্রোটোকলটি ম্যানুয়ালি আহ্বান করুন এবং ফাংশনটি আপনার উদাহরণটি উত্পন্ন করুন: আবদ্ধ হওয়ারbarFighters.__get__(a)
জন্য একটি সীমাবদ্ধ পদ্ধতি তৈরিbarFighters
করেa
।