পাইথনে ভার্চুয়াল পদ্ধতিগুলি কীভাবে প্রয়োগ করা যায়?


88

আমি পিএইচপি বা জাভা থেকে ভার্চুয়াল পদ্ধতি জানি।

কীভাবে পাইথনে এগুলি প্রয়োগ করা যেতে পারে?

বা আমি কি একটি বিমূর্ত শ্রেণিতে একটি খালি পদ্ধতি সংজ্ঞায়িত করে এটিকে ওভাররাইড করব?

উত্তর:


104

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

class Dog:
  def say(self):
    print "hau"

class Cat:
  def say(self):
    print "meow"

pet = Dog()
pet.say() # prints "hau"
another_pet = Cat()
another_pet.say() # prints "meow"

my_pets = [pet, another_pet]
for a_pet in my_pets:
  a_pet.say()

Catএবং Dogপাইথনে এমনকি এই আচরণের অনুমতি দেওয়ার জন্য একটি সাধারণ বেস শ্রেণি থেকেও বেরিয়ে আসতে হবে না - আপনি এটি নিখরচায় অর্জন করতে পারেন। এটি বলেছিল, কিছু প্রোগ্রামাররা আরও ভালভাবে ডকুমেন্ট করার জন্য টাইপিংয়ের কিছুটা কঠোরতা আরোপ করার জন্য আরও কঠোর উপায়ে তাদের শ্রেণিবৃত্তিকে সংজ্ঞায়িত করতে পছন্দ করেন । এটিও সম্ভব - উদাহরণস্বরূপ abcমানক মডিউলটি দেখুন


35
উদাহরণ হিসাবে +1। কুকুররা কোন ভাষায় "হাউ" বলে?
জেরেমিপ

4
@ জেরেমিপি: হুম, ভাল পয়েন্ট :-) আমার মনে হয় এমন ভাষাগুলিতে যেখানে "এইচ" শব্দটি "হিপ্পি" এর প্রথম বর্ণের মতো বা স্প্যানিশ ভাষায় "জাভিয়ার" এর মতো তৈরি করা হিসাবে বোঝা যায়।
এলি বেন্ডারস্কি

4
@ এলি: দুঃখিত, তবে আমি প্রশ্নের উত্তরের জন্য গুরুতর আগ্রহী ছিলাম। ইংরেজিতে তারা "ওওফ" বলে, তারা এগুলি করে না তবে এটি সেই শব্দটি যা আমরা বিড়ালদের জন্য "মিয়া" এবং গরুর জন্য "মু" ব্যবহার করে। "হাউ" কি তখন স্প্যানিশ?
জেরেমিপ

9
@ জেরেমিপি আমি নিশ্চিতভাবে জানি যে এটি পোলিশ কুকুর যা বলেছে;)
জ_কুবিক

4
@ জেরেমিপি হ্যাঁ আমি নিশ্চিত করেছি যে কুকুররা স্প্যানিশ ভাষায় "জউ" বলে এবং ইংরেজিতে যখন লেখা হয় "হাউ" :) এইচটি
স্কাইওয়ালকার

71

raise NotImplementedError()

কোনও পদ্ধতি প্রয়োগ করে না এমন "বিমূর্ত" বেস শ্রেণীর "খাঁটি ভার্চুয়াল পদ্ধতি" বাড়াতে এটি প্রস্তাবিত ব্যতিক্রম।

https://docs.python.org/3.5/library/exception.html#NotImplementedError বলেছেন:

এই ব্যতিক্রম থেকে প্রাপ্ত RuntimeError। ব্যবহারকারীর সংজ্ঞায়িত বেস ক্লাসে, বিমূর্ত পদ্ধতিগুলি যখন এই পদ্ধতিটিকে ওভাররাইড করার জন্য উদ্ভূত শ্রেণীর প্রয়োজন হয় তখন তাদের ব্যতিক্রম বাড়াতে হবে।

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

যেমন:

class Base(object):
    def virtualMethod(self):
        raise NotImplementedError()
    def usesVirtualMethod(self):
        return self.virtualMethod() + 1

class Derived(Base):
    def virtualMethod(self):
        return 1

print Derived().usesVirtualMethod()
Base().usesVirtualMethod()

দেয়:

2
Traceback (most recent call last):
  File "./a.py", line 13, in <module>
    Base().usesVirtualMethod()
  File "./a.py", line 6, in usesVirtualMethod
    return self.virtualMethod() + 1
  File "./a.py", line 4, in virtualMethod
    raise NotImplementedError()
NotImplementedError

সম্পর্কিত: পাইথনে অ্যাবস্ট্রাক্ট ক্লাস করা কি সম্ভব?


55

পাইথন পদ্ধতি সর্বদা ভার্চুয়াল।


জঘন্য পদ্ধতি বাদে।
কনস্ট্যান্টিন

4
এই উত্তরটি সত্যই ভার্চুয়াল পদ্ধতি ব্যবহারের অন্যতম প্রধান কারণ ইন্টারফেস ক্লাস বাস্তবায়নের লক্ষ্যে সহায়তা করে না।
জিন-মার্ক ভোলি

21

প্রকৃতপক্ষে, সংস্করণে ২. p অজগর অ্যাবস্ট্রাক্ট বেস ক্লাস নামে কিছু সরবরাহ করে এবং আপনি স্পষ্টভাবে এই জাতীয় ভার্চুয়াল পদ্ধতিগুলি সেট করতে পারেন:

from abc import ABCMeta
from abc import abstractmethod
...
class C:
    __metaclass__ = ABCMeta
    @abstractmethod
    def my_abstract_method(self, ...):

এটি খুব ভালভাবে কাজ করে তবে শর্ত থাকে যে ক্লাসটি ইতিমধ্যে মেটাক্লাস ব্যবহার করে এমন ক্লাসগুলির উত্তরাধিকারী না হয়।

উত্স: http://docs.python.org/2/library/abc.html


এই নির্দেশের জন্য কি পাইথন 3 সমান?
লক

9

পাইথন পদ্ধতি সর্বদা ভার্চুয়াল

যেমন ইগনাসিও এখনও বলেছেন যে কোনওরকম শ্রেণীর উত্তরাধিকার আপনি যা চান তা বাস্তবায়নের জন্য আরও ভাল পদ্ধতির হতে পারে।

class Animal:
    def __init__(self,name,legs):
        self.name = name
        self.legs = legs

    def getLegs(self):
        return "{0} has {1} legs".format(self.name, self.legs)

    def says(self):
        return "I am an unknown animal"

class Dog(Animal): # <Dog inherits from Animal here (all methods as well)

    def says(self): # <Called instead of Animal says method
        return "I am a dog named {0}".format(self.name)

    def somethingOnlyADogCanDo(self):
        return "be loyal"

formless = Animal("Animal", 0)
rover = Dog("Rover", 4) #<calls initialization method from animal

print(formless.says()) # <calls animal say method

print(rover.says()) #<calls Dog says method
print(rover.getLegs()) #<calls getLegs method from animal class

ফলাফলগুলি হওয়া উচিত:

I am an unknown animal
I am a dog named Rover
Rover has 4 legs

4

সি ++ তে ভার্চুয়াল পদ্ধতির মতো কিছু (বেস ক্লাসে একটি রেফারেন্স বা পয়েন্টারের মাধ্যমে উত্পন্ন শ্রেণীর কল্পনা পদ্ধতি প্রয়োগ) পাইথনে কোনও অর্থ দেয় না, কারণ পাইথনের টাইপিং নেই। (যদিও জাভা এবং পিএইচপি-তে ভার্চুয়াল পদ্ধতিগুলি কাজ করে তা আমি জানি না))

তবে যদি "ভার্চুয়াল" বলতে আপনার অর্থ উত্তরাধিকারের শ্রেণিবিন্যাসের সবচেয়ে নীচে বাস্তবায়নকে ডেকে আনা হয়, তবে বেশিরভাগ উত্তর হিসাবে উল্লেখ করা হয়েছে যে আপনি সর্বদা পাইথন-এ পাবেন।

বেশ, সবসময় ...

যেহেতু ডিপ্ল্যাম্প নির্দেশ করেছে, পাইথনের সমস্ত পদ্ধতি সেভাবে আচরণ করে না। ডান্ডার পদ্ধতি না। এবং আমি মনে করি এটি একটি খুব সুপরিচিত বৈশিষ্ট্য।

এই কৃত্রিম উদাহরণ বিবেচনা করুন

class A:
    def prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.prop_a()

class B(A):
    def prop_a(self):
        return 2

এখন

>>> B().prop_b()
20
>>> A().prob_b()
10

তবে এটিকে বিবেচনা করুন

class A:
    def __prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.__prop_a()

class B(A):
    def __prop_a(self):
        return 2

এখন

>>> B().prop_b()
10
>>> A().prob_b()
10

আমরা পরিবর্তন করেছি কেবলমাত্র prop_a()একটি জঘন্য পদ্ধতি তৈরি করা।

প্রথম আচরণের সাথে একটি সমস্যা হতে পারে যে আপনি এর আচরণকে prop_a()প্রভাবিত না করে উত্পন্ন শ্রেণিতে আচরণ পরিবর্তন করতে পারবেন না prop_b()। রেমন্ড হেটিঙ্গারের খুব সুন্দর এই বক্তৃতাটি এমন কোনও ক্ষেত্রে ব্যবহারের ক্ষেত্রে উদাহরণ দেয় যেখানে এটি অসুবিধাজনক।

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