একটি বিদ্যমান বস্তু উদাহরণ থেকে একটি পদ্ধতি যোগ করা

আমি পড়েছি যে পাইথনে একটি বিদ্যমান বস্তুর একটি পদ্ধতি যোগ করা সম্ভব (যেমন শ্রেণীবিন্যাসে নয়)।

আমি বুঝতে পারি যে এটা সবসময় ভাল না। কিন্তু কিভাবে এটি করতে পারে?

0

18 উত্তর

আমি পাইথন সিনট্যাক্স জানি না, কিন্তু আমি জানি ruby এটি করতে পারে, এবং এটি বরং তুচ্ছ। চলুন শুরু করা যাক আপনি Array এ একটি পদ্ধতি যুক্ত করতে চান যা দৈর্ঘ্যকে প্রমিত ছাপে:

class Array
  def print_length
    puts length
  end
end

যদি আপনি পুরো শ্রেণী সংশোধন করতে না চান, তবে আপনি শুধুমাত্র একটি অ্যারের একটি উদাহরণে পদ্ধতি যোগ করতে পারেন, এবং অন্য কোন অ্যারে পদ্ধতি থাকবে না:

array = [1, 2, 3]
def array.print_length
  puts length
end

শুধু এই বৈশিষ্ট্য ব্যবহার করে জড়িত সমস্যা সম্পর্কে সচেতন থাকুন। জেফ এটউড আসলে খুব বেশিদিন আগে এটি সম্পর্কে লিখেছেন

0
যোগ

আপনি কি খুঁজছেন খুঁজছেন সেট্যাট্র </কোড> আমি বিশ্বাস করি একটি বস্তুর উপর একটি অ্যাট্রিবিউট সেট করার জন্য এটি ব্যবহার করুন।

>>> 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>
0
যোগ
setattr (a, 'printme', printme) এর পরিবর্তে সহজভাবে এ প্রিন্টে = প্রিন্টে ব্যবহার করার কোন কারণ নেই?
যোগ লেখক Tobias Kienzler, উৎস
এটি A ক্লাসটি প্যাচিং করছে না, উদাহরণটি a নয়।
যোগ লেখক Ethan Furman, উৎস
এটি রানটাইম এ পদ্ধতি নাম গঠন করে যদি এটা জ্ঞান করে তোলে
যোগ লেখক rr-, উৎস

একটি বিদ্যমান বস্তু উদাহরণ থেকে একটি পদ্ধতি যোগ করা

     

আমি পাইথনতে একটি বিদ্যমান বস্তুর একটি পদ্ধতি (যেমন ক্লাস ডিফারেন্সে না) এ যোগ করা সম্ভব। ?

     

আমি বুঝতে পারি যে এটা সবসময় একটি ভাল সিদ্ধান্ত তাই না। কিন্তু, কীভাবে এটি করতে পারি?

হ্যাঁ, এটি সম্ভব - কিন্তু সুপারিশ করা হয় না

আমি এই সুপারিশ না। এটি একটি খারাপ ধারণা। এটা করবেন না

এখানে কয়েকটি কারণ আছে:

  • আপনি এই ক্ষেত্রে প্রতিটি ক্ষেত্রে একটি বাউন্ড অবজেক্ট যোগ করবেন। আপনি এটি অনেক কিছু করতে হলে, আপনি সম্ভবত অনেক মেমরি অপচয় করব আবদ্ধ পদ্ধতিগুলি সাধারণত শুধুমাত্র তাদের কল এর সংক্ষিপ্ত সময়ের জন্য তৈরি করা হয়, এবং তারপর স্বয়ংক্রিয়ভাবে সংগ্রহ করা আবর্জনা যখন বিদ্যমান থাকে। যদি আপনি এটি নিজে করেন, তবে আপনার কাছে আবদ্ধ পদ্ধতির একটি নাম বাঁধাই থাকবে - যা ব্যবহারে তার আবর্জনা সংগ্রহকে প্রতিরোধ করবে।
  • একটি নির্দিষ্ট প্রকারের অবজেক্টের উদাহরণগুলি সাধারণত তার ধরনের সকল বস্তুর উপর তার পদ্ধতি রয়েছে। আপনি যদি অন্য কোন পদ্ধতি যোগ করেন, তবে কিছু দৃষ্টিকোণ রয়েছে এমন পদ্ধতি এবং অন্য কেউ করবে না। প্রোগ্রামাররা এই আশা করবেন না, এবং আপনি কমপক্ষে বিস্ময়কর নিয়ম এর লঙ্ঘনের ঝুঁকি হারাবেন।
  • যেহেতু এটি করতে না পারার অন্য সত্যিই ভাল কারণ আছে, আপনি যদি তা করেন তবে আপনার নিজেরও একটি দুর্বল খ্যাতি দেবেন।

সুতরাং, আমি আপনাকে এই সত্যিই না যদি আপনি সত্যিই একটি ভাল কারণ আছে কারণ সুপারিশ। শ্রেণির সংজ্ঞা সঠিক পদ্ধতি সংজ্ঞায়িত করা ভাল বা কম বানর-প্যাচকে শ্রেণিগতভাবে সরাসরি, এইভাবে:

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)

Method nought (0) - use the descriptor method, __get__

ফাংশনগুলির উপর ডটেড লকআউটগুলি ফাংশনটির সাথে ফাংশনটির __ গেট __ </কোড> পদ্ধতিটি কল করুন, বস্তুর বস্তুটিকে বাইন্ডিংয়ের সাথে সংযুক্ত করুন এবং এইভাবে একটি "আবদ্ধ পদ্ধতি" তৈরি করুন।

foo.sample_method = sample_method.__get__(foo)

এবং এখন:

>>> foo.sample_method(1,2)
3

পদ্ধতি এক - ধরন। MethodType

প্রথমত, আমদানী প্রকারগুলি, যা থেকে আমরা পদ্ধতি কন্সট্রাকটর পেতে পারি:

import types

এখন আমরা পদ্ধতিতে পদ্ধতি যোগ করুন। এটি করার জন্য, আমরা ধরন মডিউল থেকে (যা আমরা উপরে আমদানি করেছি) থেকে MethodType কনস্ট্রাকটর প্রয়োজন।

Types.MethodType এর জন্য যুক্তি স্বাক্ষর (ফাংশন, উদাহরণ, ক্লাস) :

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

পদ্ধতি তিন: functools.partial

একটি আংশিক ফাংশন একটি ফাংশন (এবং বিকল্পরূপে কীওয়ার্ড আর্গুমেন্ট) প্রথম যুক্তি (গুলি) প্রয়োগ করে, এবং পরবর্তীতে অবশিষ্ট আর্গুমেন্ট (এবং ওভাররাইডিং কীওয়ার্ড আর্গুমেন্ট) দিয়ে বলা যেতে পারে। এভাবে:

>>> from functools import partial
>>> foo.sample_method = partial(sample_method, foo)
>>> foo.sample_method(1,2)
3    

যখন আপনি বিবেচনা করেন যে আবদ্ধ পদ্ধতিগুলি উদাহরণের আংশিক ফাংশন হয় তখন এটি বোঝায়।

অবজেক্ট ফাংশন একটি বস্তুর অ্যাট্রিবিউট হিসাবে - কেন এটি কাজ করে না:

যদি আমরা নমুনা_ম্যাথকে একইভাবে যুক্ত করতে চেষ্টা করি তবে আমরা ক্লাসে এটি যুক্ত করতে পারি, এটি দৃষ্টান্ত থেকে অবাঞ্ছিত এবং প্রথম যুক্তি হিসাবে অন্তর্নিহিত স্বকে গ্রহণ করে না।

>>> foo.sample_method = sample_method
>>> foo.sample_method(1,2)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: sample_method() takes exactly 3 arguments (2 given)

আমরা আনন্দের ফাংশন কাজ করে স্পষ্টভাবে উদাহরণ (অথবা কিছু, কারণ এই পদ্ধতিটি আসলে স্ব </কোড> আর্গুমেন্ট ভ্যারিয়েবল ব্যবহার করে না) দ্বারা পাস করতে পারে, তবে এটি অন্যান্য দৃষ্টিকোণের প্রত্যাশিত স্বাক্ষরের সাথে সঙ্গতিপূর্ণ হবে না (যদি আমরা এই উদাহরণ বানর-প্যাচিং হয়):

>>> foo.sample_method(foo, 1, 2)
3

উপসংহার

আপনি এখন অনেক উপায়ে জানেন যে আপনি এটি করতে পারেন, কিন্তু সব গম্ভীরতার মধ্যে - এটি করবেন না।

0
যোগ
আমার মন্তব্য এই রেফারেন্স উপর ভিত্তি করে ছিল: পাইথন-রেফারেন্স। io / en / latest / docs / dunderdsc / & hellip; আমি এখন অফিসিয়াল ডক্স থেকে কি দেখতে পাচ্ছি, এটি ঐচ্ছিক: docs.python.org/3/howto/descriptor.html#descriptor-protocol
যোগ লেখক Aidas Bendoraitis, উৎস
__ পেতে __ </ কোড> পদ্ধতিকে পরবর্তী প্যারামিটার হিসাবে ক্লাসের প্রয়োজন হয়: sample_method .__ get __ (foo, Foo)
যোগ লেখক Aidas Bendoraitis, উৎস
@ এডেসব্যান্ডোরাটিস আমি এটা "প্রয়োজন" বলব না, এটি একটি ঐচ্ছিক পরামিতি যা বর্ণনাকারী প্রোটোকল প্রয়োগ করার সময় সরবরাহ করা হয় - কিন্তু পাইথন ফাংশনটি যুক্তি ব্যবহার করে না: github.com/python/cpython/blob/master/Objects/funcobject.c#L‌ 581
যোগ লেখক Aaron Hall, উৎস
@ এটকোড আমি ভূমিকাতে এই কাজটি এড়াতে কারণগুলির উপর প্রসারিত করেছি।
যোগ লেখক Aaron Hall, উৎস
দাবী পরিত্যাগ আমি কি সম্পর্কে আশ্চর্য ছিল। পদ্ধতি সংজ্ঞা কেবল ক্লাস সংজ্ঞা মধ্যে নেস্টেড ফাংশন হয়।
যোগ লেখক Atcold, উৎস

Module new is deprecated since python 2.6 and removed in 3.0, use types

see 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 
0
যোগ

types. Method method ছাড়া একটি পদ্ধতিতে একটি পদ্ধতি সংযুক্ত করার জন্য অন্তত দুটি উপায় রয়েছে:

>>> 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
<__main__.A instance at 0x973ec6c>>
>>> 
>>> def foo(firstargument):
...  print 'im foo, invoked with: ', firstargument

>>> foo

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
<__main__.A instance at 0x973ec6c>>

2:

>>> instancemethod = type(A.m)
>>> instancemethod

>>> a.foo2 = instancemethod(foo, a, type(a))
>>> a.foo2()
im foo, invoked with:  <__main__.A instance at 0x973ec6c>
>>> a.foo2
<__main__.A instance at 0x973ec6c>>

Useful links:
Data model - invoking descriptors
Descriptor HowTo Guide - invoking descriptors

0
যোগ

এই প্রশ্নটি অ-পাইথন সংস্করণের জন্য জিজ্ঞাসা করা হয়েছে, এখানে জাভাস্ক্রিপ্ট:

a.methodname = function() { console.log("Yay, a new method!") }
0
যোগ

আমি মনে করি উপরের উত্তর মূল পয়েন্ট মিস।

চলুন একটি পদ্ধতিতে একটি ক্লাস আছে:

class A(object):
    def m(self):
        pass

এখন, আইফাইথনে এর সাথে খেলতে দিন:

In [2]: A.m
Out[2]: 

ঠিক আছে, তাই m() একরকম A এর একটি অপ্রয়োজনীয় পদ্ধতি হয়ে ওঠে। কিন্তু এটা কি আসলেই ভালো?

In [5]: A.__dict__['m']
Out[5]: 

এটি দেখায় যে m() শুধু একটি ফাংশন, যার জন্য A ক্লাস অভিধানে যোগ করা হয় - কোনও জাদু নেই। তাহলে কেন এ। এম আমাদের একটি আনবাউড পদ্ধতি দেয়? এটা কারণ ডট একটি সহজ অভিধান সন্ধান করতে অনুবাদ করা হয় না। এটি আসলে একটি .__ শ্রেণি কল এর একটি __.__ getattribute __ (A, 'M'):

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
 - m
 - m

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

এখন, ডিফল্ট __getattribute__ কি এটি পরীক্ষা করে দেখায় যে যদি অ্যাট্রিবিউটটি তথাকথিত হয় তবে বর্ণনাকারী বা না, অর্থাৎ যদি এটি একটি বিশেষ __get__ পদ্ধতি প্রয়োগ করে। যদি এটি সেই পদ্ধতি প্রয়োগ করে, তাহলে যেটা ফেরত দেওয়া হয় সেটি __get__ পদ্ধতিতে কল করার ফলাফল। আমাদের A ক্লাসের প্রথম সংস্করণে ফিরে যাওয়া, এটি আমাদের আছে:

In [28]: A.__dict__['m'].__get__(None, A)
Out[28]: 

এবং পাইথন ফাংশন ডিস্ক্রিপ্টর প্রোটোকল বাস্তবায়ন করে, যদি তারা একটি অবজেক্টের পক্ষে বলা হয় তবে তারা তাদের __get__ পদ্ধতিতে সেই বস্তুর সাথে নিজেদের সংযুক্ত করে।

ঠিক আছে, তাই কিভাবে একটি বিদ্যমান বস্তুর একটি পদ্ধতি যোগ করতে? মনে হচ্ছে আপনি প্যাচিং ক্লাস মনে রাখবেন না, এটা যেমন সহজ:

B.m = m

তারপর B.m "অসীম পদ্ধতি" হয়ে যায়, বর্ণনাকারী জাদুটির জন্য ধন্যবাদ।

এবং যদি আপনি একটি একক বস্তুতে শুধুমাত্র একটি পদ্ধতি যোগ করতে চান, তাহলে আপনি আপনার নিজের পদ্ধতি অনুসরণ করতে হবে types. Method পদ্ধতি ব্যবহার করে:

b.m = types.MethodType(m, b)

উপায় দ্বারা:

In [2]: A.m
Out[2]: 

In [59]: type(A.m)
Out[59]: 

In [60]: type(b.m)
Out[60]: 

In [61]: types.MethodType
Out[61]: 

0
যোগ

এই প্রশ্নটি বছর আগে খোলা ছিল, কিন্তু হে, একটি সজ্জা ব্যবহার করে একটি বর্গ উদাহরণ একটি ফাংশন বাঁধাই একটি সহজ উপায় আছে:

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 ()

There, when you pass the function and the instance to the binder decorator, it will create a new function, with the same code object as the first one. Then, the given instance of the class is stored in an attribute of the newly created function. The decorator return a (third) function calling automatically the copied function, giving the instance as the first parameter.

In conclusion you get a function simulating it's binding to the class instance. Letting the original function unchanged.

0
যোগ

জেসন প্র্যাট এবং সম্প্রদায় উইকি উত্তরগুলি একত্রিত করে, বাঁধনের বিভিন্ন পদ্ধতির ফলাফলগুলি দেখে:

বিশেষ করে নোট কিভাবে বাঁধন ফাংশন একটি বর্গ পদ্ধতি হিসাবে কাজ করে যোগ করা, কিন্তু রেফারেন্সিং সুযোগ ভুল।

#!/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__ <__main__.C instance at 0x000000000230FD88>>
# addmethod <__main__.C instance at 0x000000000230FD88>>
# f0 <__main__.C instance at 0x000000000230FD88>>

print '\nattributes of b:'
listattr(b)
# OUT:
# attributes of b:
# __init__ <__main__.C instance at 0x000000000230FE08>>
# addmethod <__main__.C instance at 0x000000000230FE08>>
# f0 <__main__.C instance at 0x000000000230FE08>>
# f1 >
# f2 <__main__.C instance at 0x000000000230FE08>>
# f3 <__main__.C instance at 0x000000000230FE08>>
# f4 <__main__.C instance at 0x000000000230FE08>>

print '\nattributes of c:'
listattr(c)
# OUT:
# attributes of c:
# __init__ <__main__.C instance at 0x0000000002313108>>
# addmethod <__main__.C instance at 0x0000000002313108>>
# f0 <__main__.C instance at 0x0000000002313108>>

ব্যক্তিগতভাবে, আমি বহিরাগত ADDMETHOD ফাংশন রুট পছন্দ করি, এটি আমাকে গতিশীলভাবে একটি iterator মধ্যে নতুন পদ্ধতি নাম বরাদ্দ করতে পারবেন হিসাবে ভাল।

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__ <__main__.C instance at 0x0000000002303508>>
# addmethod <__main__.C instance at 0x0000000002303508>>
# f0 <__main__.C instance at 0x0000000002303508>>
# f1 <__main__.C instance at 0x0000000002303508>>
# f2 <__main__.C instance at 0x0000000002303508>>
# f3 <__main__.C instance at 0x0000000002303508>>
# f4 <__main__.C instance at 0x0000000002303508>>
0
যোগ
addmethod নিম্নলিখিত উপায়ে পুনরায় লিখিত হয় ডিফল্ট addmethod (স্ব, পদ্ধতি, নাম): স্ব। ডাইরেক্ট __ [নাম] = ধরন। পদ্ধতি টাইপ (পদ্ধতি, স্ব) </ কোড> সমস্যার সমাধান করে
যোগ লেখক Antony Hatchkins, উৎস

Python বানর প্যাচিং সাধারণত সাধারণত আপনার নিজের সঙ্গে একটি ক্লাস বা ফাংশন স্বাক্ষর overwriting দ্বারা কাজ করে। নিচে Zope Wiki এর একটি উদাহরণ রয়েছে:

from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
   return "ook ook eee eee eee!"
SomeClass.speak = speak

যে কোড ক্লাসের উপর কথা বলতে বলা একটি পদ্ধতি মুছে ফেলা হবে / তৈরি করা হবে জেফ Atwood এর মধ্যে বানর প্যাচিং নেভিগেশন সাম্প্রতিক পোস্ট তিনি সি # 3.0 তে একটি উদাহরণ দেখান যা বর্তমান কাজের জন্য আমি ব্যবহার করি।

0
যোগ
কিন্তু এটি সব ক্লাসের দৃষ্টিকোণকে প্রভাবিত করে না, কেবল মাত্র এক।
যোগ লেখক glglgl, উৎস

Python মধ্যে, ফাংশন এবং আবদ্ধ পদ্ধতি মধ্যে একটি পার্থক্য আছে।

>>> def foo():
...     print "foo"
...
>>> class A:
...     def bar( self ):
...         print "bar"
...
>>> a = A()
>>> foo

>>> a.bar
<__main__.A instance at 0x00A9BC88>>
>>>

আবদ্ধ পদ্ধতিগুলি একটি উদাহরণে "আবদ্ধ" (কিভাবে বর্ণনামূলক) হয়েছে, এবং এই পদ্ধতিটি যখনই বলা হয় তখন প্রথম যুক্তি হিসাবে পাস করা হবে।

Callables যে একটি ক্লাসের বৈশিষ্ট্যাবলী (একটি ইনস্ট্যান্সের বিপরীত) এখনও অবাঞ্ছিত, যদিও, আপনি চাইলে ক্লাস সংজ্ঞা পরিবর্তন করতে পারেন:

>>> def fooFighters( self ):
...     print "fooFighters"
...
>>> A.fooFighters = fooFighters
>>> a2 = A()
>>> a2.fooFighters
<__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 "", line 1, in 
TypeError: barFighters() takes exactly 1 argument (0 given)

ফাংশনটি যখন স্বয়ংক্রিয়ভাবে একটি ইনস্ট্যান্সে সংযুক্ত হয় তখন তা স্বয়ংক্রিয়ভাবে আবদ্ধ হয় না:

>>> a.barFighters

এটি আবদ্ধ করতে, আমরা প্রকারের মডিউলে MethodType ফাংশন ব্যবহার করতে পারি </একটি>:

>>> import types
>>> a.barFighters = types.MethodType( barFighters, a )
>>> a.barFighters
<__main__.A instance at 0x00A9BC88>>
>>> a.barFighters()
barFighters

এই সময় ক্লাসের অন্যান্য উদাহরণ প্রভাবিত হয় নি:

>>> a2.barFighters()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: A instance has no attribute 'barFighters'

আরো তথ্যের জন্য

বর্ণনাকারী এবং metaclass প্রোগ্রামিং

0
যোগ
পাইথন মধ্যে আবদ্ধ পদ্ধতি C# এক্সটেনশন পদ্ধতি অনুরূপ?
যোগ লেখক Andy, উৎস
@ এন্ডারম্যানএইচপিএম: বেশিরভাগ: ঠিক একই রকম কাজ চালিয়ে যাওয়ার সম্ভাবনা বেশি, একই সাথে এটিকে কীভাবে একটি দৃষ্টান্তের বৈশিষ্ট্যটি ব্যবহার করা যায়। এটি classmethod এবং স্ট্যাটিক মাপ এবং অন্যান্য বর্ণালীগুলির জন্যও কাজ করবে। এটি অন্য একটি আমদানি সঙ্গে নামস্থান cluttering এড়াতে।
যোগ লেখক Martijn Pieters, উৎস
প্রস্তাবিত বিবৃতির পদ্ধতির জন্য পূর্ণ কোড হল a.barFighters = barFighters .__ Get __ (a)
যোগ লেখক eqzx, উৎস
@MartijnPieters ডিস্ক্রিপ্টর প্রোটোকল </ কোড> ব্যবহার করে বজায় রাখার কোনও সুবিধা যেমন একটি MethodType তৈরি করে, এটি হয়তো একটু বেশি পঠনযোগ্য।
যোগ লেখক EndermanAPM, উৎস

জেসন প্র্যাট পোস্ট করেছেন কি সঠিক?

>>> class Test(object):
...   def a(self):
...     pass
... 
>>> def b(self):
...   pass
... 
>>> Test.b = b
>>> type(b)

>>> type(Test.a)

>>> type(Test.b)

আপনি দেখতে পাচ্ছেন যে, পাইথনটি() এর চেয়ে ভিন্ন কোনটি বি() কে বিবেচনা করে না। Python সব পদ্ধতি শুধুমাত্র ফাংশন হতে যে ভেরিয়েবল।

0
যোগ
আপনি ক্লাসটি প্যাচিং করছেন টেস্ট </ কোড>, এটির একটি উদাহরণ নয়।
যোগ লেখক Ethan Furman, উৎস

আপনি অবশ্যই অবশ্যই নিষিদ্ধ ফল এ দেখতে পাবেন, এটি একটি পাইথন লাইব্রেরি যা বানরকে কোনও Python শ্রেণীর প্যাচিং সমর্থন করে, এমনকি স্ট্রিং

0
যোগ
সাধারনত, একটি টুল বা লাইব্রেরির লিঙ্কগুলি ব্যবহার নোট বা কিছু নমুনা কোড সহ , অথবা যদি সম্ভব হয় উভয়ই। যাইহোক, এটি কমপক্ষে লিঙ্কযুক্ত পোস্টের সর্বনিম্ন মান পূরণ করে কীভাবে লিঙ্কটি সম্পর্কিত সমস্যাটি প্রযোজ্য সে বিষয়ে নির্দিষ্ট ব্যাখ্যা অন্তর্ভুক্ত করে।
যোগ লেখক Nathan Tuggy, উৎস

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

ফাংশন ব্যবহার করে সুই() নামক একটি মডিউল প্যাচ করুন guineapig নিম্নরূপঃ

import gorilla
import guineapig
@gorilla.patch(guineapig)
def needle():
    print("awesome")

কিন্তু এটি আরো আকর্ষণীয় ব্যবহারের ক্ষেত্রে যত্নশীল করে যেমন FAQ এ প্রদর্শিত হয় ডকুমেন্টেশন

কোড GitHub এ উপলব্ধ।

0
যোগ

আপনি একটি উদাহরণ একটি পদ্ধতি বাঁধতে Lambda ব্যবহার করতে পারেন:

def run(self):
    print self._instanceString

class A(object):
    def __init__(self):
        self._instanceString = "এই উদাহরণ স্ট্রিং"

a = A()
a.run = lambda: run(a)
a.run()

এই উদাহরণ স্ট্রিং

প্রারম্ভ কোড ছাড়াই প্রক্রিয়াটি শেষ

0
যোগ

এই "জেসন Pratt" এর উত্তর আসলে একটি addon

যদিও জেসস কাজ করেন, তবে এটি কেবল কাজ করে যদি কেউ একটি ক্লাসে একটি ফাংশন যুক্ত করতে চায়। এটি .py উত্স কোড ফাইল থেকে ইতিমধ্যে বিদ্যমান পদ্ধতি পুনরায় লোড করার চেষ্টা করে যখন এটি আমার জন্য কাজ না।

এটি একটি সমাধান খুঁজে পেতে বয়সের জন্য আমাকে গ্রহণ, কিন্তু কৌতুক সহজ মনে হয় ... 1.সোর্স কোড ফাইল থেকে কোড আমদানি 2. একটি পুনরায় লোড বলুন 3.rd ব্যবহার types.FunctionType (...) একটি ফাংশন এ আমদানি করা এবং আবদ্ধ পদ্ধতি রূপান্তর আপনি বর্তমান বিশ্বব্যাপী ভেরিয়েবলগুলি পাশ করতে পারেন, যেহেতু পুনরায় লোড করা পদ্ধতি একটি ভিন্ন নামস্থান 4. এখন আপনি "জেসন Pratt" দ্বারা প্রস্তাবিত হিসাবে অবিরত করতে পারেন   types.MethodType (...) ব্যবহার করে

উদাহরণ:

# 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
0
যোগ

আমি এটা অদ্ভুত যে কেউ উল্লিখিত যে উপরে তালিকাভুক্ত সব পদ্ধতি যোগ পদ্ধতি এবং উদাহরণের মধ্যে একটি চক্র রেফারেন্স তৈরি, বস্তু আবর্জনা সংগ্রহ পর্যন্ত স্থির হতে যার ফলে একটি পুরানো কৌতুক বস্তুর বর্গ প্রসারিত দ্বারা একটি বর্ণনাকারী যোগ ছিল:

def addmethod(obj, name, func):
    klass = obj.__class__
    subclass = type(klass.__name__, (klass,), {})
    setattr(subclass, name, func)
    obj.__class__ = subclass
0
যোগ
from types import MethodType

def method(self):
   print 'hi!'


setattr( targetObj, method.__name__, MethodType(method, targetObj, type(method)) )

এই সঙ্গে, আপনি স্ব পয়েন্টার ব্যবহার করতে পারেন

0
যোগ