পাইথনে কি কোনও স্তরের উদাহরণ স্তরে কোনও শ্রেণি পদ্ধতিকে ওভাররাইড করার উপায় আছে? উদাহরণ স্বরূপ:
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
boby.bark() # WoOoOoF!!
উত্তর:
প্রদর্শিত হিসাবে এটি করবেন না দয়া করে। শ্রেণি থেকে আলাদা হওয়ার জন্য আপনি কোনও উদাহরণটি বানরক্ষেত্রের সময় আপনার কোডটি অপঠনযোগ্য হয়ে যায়।
আপনি বানরপ্যাচড কোডটি ডিবাগ করতে পারবেন না।
আপনি যখন কোনও বাগ খুঁজে পান bobyএবং print type(boby)আপনি দেখতে পাবেন যে (ক) এটি একটি কুকুর, তবে (খ) কিছু অস্পষ্ট কারণে এটি সঠিকভাবে ছাঁটাই না। এটি দুঃস্বপ্ন। এটি করবেন না.
পরিবর্তে এটি করুন।
class Dog:
def bark(self):
print "WOOF"
class BobyDog( Dog ):
def bark( self ):
print "WoOoOoF!!"
otherDog= Dog()
otherDog.bark() # WOOF
boby = BobyDog()
boby.bark() # WoOoOoF!!
হ্যাঁ এটা সম্ভব:
class Dog:
def bark(self):
print "Woof"
def new_bark(self):
print "Woof Woof"
foo = Dog()
funcType = type(Dog.bark)
# "Woof"
foo.bark()
# replace bark with new_bark for this object only
foo.bark = funcType(new_bark, foo, Dog)
foo.bark()
# "Woof Woof"
funcTypeএটি কী করে বিশেষত কী করে এবং কেন এটি প্রয়োজনীয় তা ব্যাখ্যা করুন ।
funcType = types.MethodType(আমদানির পরে types) ব্যবহার করে এটিকে কিছুটা সহজ এবং আরও স্পষ্ট করা যায় funcType = type(Dog.bark)।
__get__এটিকে উদাহরণের সাথে আবদ্ধ করতে ফাংশনটিতে কল করতে পারেন ।
আপনাকে মডিউলটি থেকে মেথডটাইপ ব্যবহার করতে হবে types। এর উদ্দেশ্য MethodTypeহ'ল উদাহরণ স্তরের পদ্ধতিগুলি ওভাররাইট করা (যাতে এটি selfওভাররাইট পদ্ধতিতে উপলব্ধ হতে পারে)।
নীচের উদাহরণ দেখুন।
import types
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
def _bark(self):
print "WoOoOoF!!"
boby.bark = types.MethodType(_bark, boby)
boby.bark() # WoOoOoF!!
@ কোডেলজিকের দুর্দান্ত উত্তরটি ব্যাখ্যা করতে, আমি আরও স্পষ্ট পদ্ধতির প্রস্তাব দিই। এটি একই কৌশলটি যা .অপারেটর কোনও শ্রেণি পদ্ধতিতে বাঁধতে সম্পূর্ণরূপে যায় যখন আপনি এটিকে উদাহরণ বৈশিষ্ট্য হিসাবে অ্যাক্সেস করেন তবে আপনার পদ্ধতিটি আসলে কোনও শ্রেণীর বাইরে সংজ্ঞায়িত একটি ফাংশন হবে।
@ কোডেলোগিক কোডের সাথে কাজ করা, পদ্ধতিটি কীভাবে আবদ্ধ তা কেবলমাত্র পার্থক্য। আমি এই সত্যটি ব্যবহার করছি যে ফাংশন এবং পদ্ধতিগুলি পাইথনের ডেটাবিহীন বর্ণনাকারী এবং __get__পদ্ধতিটি আহ্বান করে । বিশেষত লক্ষ্য করুন যে আসল এবং প্রতিস্থাপন উভয়েরই অভিন্ন স্বাক্ষর রয়েছে যার অর্থ আপনি প্রতিস্থাপনটি একটি সম্পূর্ণ শ্রেণীর পদ্ধতি হিসাবে লিখতে পারেন, যার মাধ্যমে সমস্ত উদাহরণ বৈশিষ্ট্য অ্যাক্সেস করে self।
ক্লাস কুকুর:
ডিএফ বার্ক (স্ব):
"ওওফ" মুদ্রণ করুন
Def new_bark (স্ব):
"ওয়ুফ ওয়ুফ" মুদ্রণ
foo = কুকুর ()
# "ওওফ"
foo.bark ()
# কেবল এই বস্তুর জন্য বার্ককে নতুন_বার্কের সাথে প্রতিস্থাপন করুন
foo.bark = নতুন_বার্ক .__ পান __ (ফু, কুকুর)
foo.bark ()
# "বুনন বুনন"
একটি উদাহরণ বৈশিষ্ট্যের সাথে আবদ্ধ পদ্ধতিটি নির্ধারণ করে আপনি কোনও পদ্ধতিকে ওভাররাইড করার প্রায় সম্পূর্ণ সিমুলেশন তৈরি করেছেন। অনুপস্থিত একটি সহজ বৈশিষ্ট্য হ'ল নো-আরগ সংস্করণে অ্যাক্সেস করা super, যেহেতু আপনি শ্রেণির সংজ্ঞায় নেই। আরেকটি বিষয় হ'ল __name__আপনার আবদ্ধ পদ্ধতির বৈশিষ্ট্যটি শ্রেণীর সংজ্ঞা অনুসারে এটি যে ক্রিয়াকে ওভাররাইড করছে তার নাম নেবে না, তবে আপনি এখনও এটিকে ম্যানুয়ালি সেট করতে পারেন। তৃতীয় তফাতটি হ'ল আপনার ম্যানুয়ালি-আবদ্ধ পদ্ধতিটি একটি সরল বৈশিষ্ট্য রেফারেন্স যা কেবল কোনও ফাংশন হিসাবে ঘটে। .অপারেটর কিছুই না কিন্তু যে রেফারেন্স আনা। অন্যদিকে কোনও উদাহরণ থেকে নিয়মিত পদ্ধতিতে প্রার্থনা করার সময়, বাধ্যতামূলক প্রক্রিয়া প্রতিবার একটি নতুন বাউন্ড পদ্ধতি তৈরি করে।
এটি যেভাবে কাজ করে তার একমাত্র কারণ, এই উদাহরণটি অ-ডেটা বিবরণকারীকে ওভাররাইড করে । ডেটা বর্ণনাকারীদের __set__পদ্ধতি রয়েছে, কোন পদ্ধতিগুলি (সৌভাগ্যক্রমে আপনার জন্য) তা নয়। ক্লাসে ডেটা বর্ণনাকারীরা আসলে কোনও উদাহরণের বৈশিষ্ট্যের তুলনায় অগ্রাধিকার নেন। এজন্য আপনি কোনও সম্পত্তি বরাদ্দ করতে পারেন: __set__আপনি যখন কোনও অ্যাসাইনমেন্ট করার চেষ্টা করবেন তখন তাদের পদ্ধতিটি চাওয়া হয়। আমি ব্যক্তিগতভাবে এটিকে আরও একধাপ এগিয়ে নিয়ে যেতে চাইছি এবং উদাহরণের অন্তর্নিহিত গুণাবলীর প্রকৃত মানটি আড়াল করতে চাই __dict__, যেখানে সম্পত্তিটি এর ছায়া গোছায় তাই এটি স্বাভাবিক উপায়ে অ্যাক্সেসযোগ্য।
আপনার মনে রাখা উচিত যে এটি যাদু (ডাবল আন্ডারস্কোর) পদ্ধতিগুলির জন্য অর্থহীন । যাদু পদ্ধতিগুলি অবশ্যই এইভাবে ওভাররাইড করা যেতে পারে, তবে যে ক্রিয়াকলাপগুলি সেগুলি ব্যবহার করে তা কেবল প্রকারের দিকে নজর দেয়। উদাহরণস্বরূপ, আপনি __contains__আপনার উদাহরণে বিশেষ কিছু সেট করতে পারেন , তবে কলিং এটিকে x in instanceউপেক্ষা করে type(instance).__contains__(instance, x)পরিবর্তে ব্যবহার করবে । পাইথন ডেটা মডেলটিতে নির্দিষ্ট করা সমস্ত ম্যাজিক পদ্ধতিতে এটি প্রযোজ্য ।
class Dog:
def bark(self):
print "WOOF"
boby = Dog()
boby.bark() # WOOF
# METHOD OVERRIDE
def new_bark():
print "WoOoOoF!!"
boby.bark = new_bark
boby.bark() # WoOoOoF!!
bobyআপনার প্রয়োজন হলে আপনি ফাংশনের অভ্যন্তরে পরিবর্তনশীলটি ব্যবহার করতে পারেন । যেহেতু আপনি কেবলমাত্র এই এক উদাহরণের জন্য পদ্ধতিটিকে ওভাররাইড করছেন তাই এই উপায়টি সহজ এবং ব্যবহারের মতো ঠিক একই প্রভাব ফেলে self।
patchingএবং এটি করার সঠিক উপায় এটি (যেমন boby = Dog()এবং boby.bark = new_bark)। এটি নিয়ন্ত্রণের জন্য ইউনিট পরীক্ষায় অবিশ্বাস্যভাবে কার্যকর । আরও ব্যাখ্যার জন্য দেখুন tryolabs.com/blog/2013/07/05/run-time-method-patching-python (উদাহরণ) - না আমি লিঙ্কযুক্ত সাইট বা লেখকের সাথে অনুমোদিত নই।
যেহেতু functools.partialএখানে কেউ উল্লেখ করছে না:
from functools import partial
class Dog:
name = "aaa"
def bark(self):
print("WOOF")
boby = Dog()
boby.bark() # WOOF
def _bark(self):
print("WoOoOoF!!")
boby.bark = partial(_bark, boby)
boby.bark() # WoOoOoF!!
যেহেতু ফাংশন পাইথনে প্রথম শ্রেণীর অবজেক্ট হয় আপনি নিজের শ্রেণি অবজেক্টটি শুরু করার সময় সেগুলি পাস করতে পারেন বা প্রদত্ত শ্রেণীর উদাহরণের জন্য যে কোনও সময় ওভাররাইড করতে পারেন:
class Dog:
def __init__(self, barkmethod=None):
self.bark=self.barkp
if barkmethod:
self.bark=barkmethod
def barkp(self):
print "woof"
d=Dog()
print "calling original bark"
d.bark()
def barknew():
print "wooOOOoof"
d1=Dog(barknew)
print "calling the new bark"
d1.bark()
def barknew1():
print "nowoof"
d1.bark=barknew1
print "calling another new"
d1.bark()
এবং ফলাফল হয়
calling original bark
woof
calling the new bark
wooOOOoof
calling another new
nowoof
যদিও এস। লটের কাছ থেকে উত্তরাধিকারের ধারণাটি আমি পছন্দ করেছি এবং 'টাইপ (এ)' বিষয়টির সাথে একমত, তবে যেহেতু ফাংশনগুলিতেও অ্যাক্সেসযোগ্য বৈশিষ্ট্য রয়েছে তাই আমি মনে করি এটি এইভাবে পরিচালনা করা যায়:
class Dog:
def __init__(self, barkmethod=None):
self.bark=self.barkp
if barkmethod:
self.bark=barkmethod
def barkp(self):
"""original bark"""
print "woof"
d=Dog()
print "calling original bark"
d.bark()
print "that was %s\n" % d.bark.__doc__
def barknew():
"""a new type of bark"""
print "wooOOOoof"
d1=Dog(barknew)
print "calling the new bark"
d1.bark()
print "that was %s\n" % d1.bark.__doc__
def barknew1():
"""another type of new bark"""
print "nowoof"
d1.bark=barknew1
print "another new"
d1.bark()
print "that was %s\n" % d1.bark.__doc__
এবং আউটপুটটি হ'ল:
calling original bark
woof
that was original bark
calling the new bark
wooOOOoof
that was a new type of bark
another new
nowoof
that was another type of new bark
প্রিয় এটি ওভাররাইড করছে না আপনি কেবল একই ফাংশনটির সাথে দুটি বার কল করছেন। মূলত ওভাররাইডিং একাধিক শ্রেণীর সাথে সম্পর্কিত। যখন একই স্বাক্ষর পদ্ধতিটি বিভিন্ন শ্রেণিতে উপস্থিত থাকে তখন আপনার কোন ফাংশনটি এটি কল করছে সেটিকে সিদ্ধান্ত নেওয়ার সিদ্ধান্ত নেয় who অজাইরাইড করা সম্ভব যখন আপনি একাধিক শ্রেণি তৈরি করেন একই ফাংশন এবং আরও একটি বিষয় ভাগ করে জানান যে অজগরটিতে ওভারলোডিং অনুমোদিত নয়
আমি এটি মূল প্রশ্নের সবচেয়ে সঠিক উত্তর বলে মনে করেছি
https://stackoverflow.com/a/10829381/7640677
import a
def _new_print_message(message):
print "NEW:", message
a.print_message = _new_print_message
import b
b.execute()