স্ট্যাটিকমেডো এবং ক্লাসমেডোথের মধ্যে পার্থক্য


3579

সজ্জিত কোনও ফাংশন @staticmethodএবং সজ্জিত একটির মধ্যে পার্থক্য কী @classmethod?


11
পরিচ্ছন্নতার স্বার্থে অজগরটিতে মডিউল স্তরের ফাংশন হিসাবে স্থির পদ্ধতিগুলি কখনও কখনও আরও ভাল হয়। একটি মডিউল ফাংশন দিয়ে আপনার প্রয়োজনীয় ক্রিয়াকলাপটি আমদানি করা এবং অপ্রয়োজনীয় প্রতিরোধ করা আরও সহজ "। বাক্যবিন্যাস (আমি আপনার দিকে লক্ষ্য করছি)) ক্লাস পদ্ধতিগুলির আরও ব্যবহার রয়েছে যেহেতু এগুলি "ফ্যাক্টরি প্যাটার্ন" ফাংশন তৈরি করতে পলিমারফিজমের সাথে একত্রে ব্যবহার করা যেতে পারে। এটি কারণ শ্রেণি পদ্ধতিগুলি অন্তর্নিহিত পরামিতি হিসাবে ক্লাস গ্রহণ করে।
FistOfFury

27
tl; dr >> সাধারণ পদ্ধতির তুলনায়, স্থির পদ্ধতি এবং শ্রেণিক পদ্ধতিগুলিও বর্গ ব্যবহার করে অ্যাক্সেস করা যায় তবে শ্রেণি পদ্ধতির বিপরীতে স্থির পদ্ধতিগুলি উত্তরাধিকারের মাধ্যমে অপরিবর্তনীয়।
imsrgadich


আরও সুনির্দিষ্ট youtube.com/watch?v=HTLu2DFOdTg&feature=youtu.be&t=2689 বিকল্প কন্সট্রাক্টরগুলির জন্য আপনার কেবল শ্রেণিবদ্ধ প্রয়োজন। অন্যথায় আপনি স্ট্যাটিকমেডোথ ব্যবহার করতে পারেন এবং ক্লাসমেথের মতো ক্লসের পরিবর্তে কোনওরকম আরও তথ্যযুক্ত প্রকৃত "CLASSNAME" দ্বারা যে কোনও শ্রেণির অ্যাট্রিবিউটের (দ্বারা। / ডট) অ্যাক্সেস করতে পারেন
রবার্ট নওক

উত্তর:


3136

হয়তো উদাহরণ কোড একটি বিট সহায়তা করবে: নোটিশ পার্থক্য কল স্বাক্ষরে foo, class_fooএবং static_foo:

class A(object):
    def foo(self, x):
        print "executing foo(%s, %s)" % (self, x)

    @classmethod
    def class_foo(cls, x):
        print "executing class_foo(%s, %s)" % (cls, x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" % x    

a = A()

নীচে কোনও অবজেক্ট দৃষ্টান্ত কোনও পদ্ধতিটিকে কল করে way অবজেক্ট উদাহরণস্বরূপ, aপ্রথম যুক্তি হিসাবে সুস্পষ্টভাবে পাস করা হয়।

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

শ্রেণীবদ্ধদের সাথে , অবজেক্ট দৃষ্টান্তের শ্রেণিটি স্পষ্টভাবে পরিবর্তে প্রথম আর্গুমেন্ট হিসাবে পাস করা হয় self

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

আপনি class_fooক্লাস ব্যবহার করে কল করতে পারেন । আসলে, আপনি যদি কোনও কিছুকে শ্রেণীবদ্ধ হিসাবে সংজ্ঞায়িত করেন তবে এটি সম্ভবত কোনও শ্রেণীর উদাহরণের চেয়ে ক্লাস থেকে কল করার ইচ্ছার কারণ। A.foo(1)একটি টাইপ এরির উত্থাপিত হবে, কিন্তু A.class_foo(1)ঠিক কাজ করে:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

শ্রেণীর পদ্ধতির জন্য লোকেরা যে ব্যবহার খুঁজে পেয়েছে তা হ'ল উত্তরাধিকারসূত্রে বিকল্প কন্সট্রাক্টর তৈরি করা ।


স্ট্যাটিকমেথডসের সাথে , self(বস্তুর উদাহরণ) বা cls(শ্রেণি) কোনওভাবেই প্রথম যুক্তি হিসাবে স্পষ্টভাবে পাস করা হয় না। তারা সরল ফাংশনগুলির মতো আচরণ করে ব্যতীত আপনি কোনও উদাহরণ বা শ্রেণী থেকে তাদের কল করতে পারেন:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

স্ট্যাটিকমেডোডগুলি ক্লাসের সাথে কোনও শ্রেণির সাথে কিছু যুক্তিসঙ্গত সংযোগযুক্ত গ্রুপ ফাংশনে ব্যবহৃত হয়।


fooকেবল একটি ফাংশন, তবে যখন আপনি কল করবেন a.fooআপনি কেবল ফাংশনটি পাবেন না, আপনি ফাংশনের aপ্রথম আর্গুমেন্ট হিসাবে আবদ্ধ বস্তুর উদাহরণ সহ ফাংশনের একটি "আংশিক প্রয়োগ" সংস্করণ পাবেন। foo2 টি যুক্তি প্রত্যাশা করে, যখন a.fooকেবল 1 টি যুক্তি প্রত্যাশা করে।

aআবদ্ধ হয় foo। নীচে "আবদ্ধ" শব্দটি দ্বারা এটি বোঝানো হয়েছে:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

সাথে a.class_foo, aআবদ্ধ নয় class_foo, বরং শ্রেণি Aআবদ্ধ class_foo

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

এখানে, একটি স্ট্যাটিকমেডোথের সাথে, যদিও এটি একটি পদ্ধতি হলেও a.static_fooস্রেফ একটি ভাল 'ওলে ফাংশনটি দেয় কোনও আর্গুমেন্টকে আবদ্ধ না করে। static_foo1 টি আর্গুমেন্ট a.static_fooপ্রত্যাশা করে এবং 1 টি যুক্তিও প্রত্যাশা করে।

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

এবং অবশ্যই একই জিনিসটি ঘটে যখন আপনি পরিবর্তে static_fooক্লাসের সাথে কল করবেন A

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

182
স্ট্যাটিকমেডোথ ব্যবহার করার জন্য কী ধরা পড়েছে তা আমি বুঝতে পারি না। আমরা কেবলমাত্র ক্লাসের বাইরে সাধারণ ফাংশনটি ব্যবহার করতে পারি।
অ্যালকোট

372
@ অ্যালকোট: আপনি কোনও ফাংশনটিকে ক্লাসে স্থানান্তর করতে চাইতে পারেন কারণ এটি যৌক্তিকভাবে শ্রেণীর সাথে সম্পর্কিত। পাইথন সোর্স কোডে (যেমন মাল্টিপ্রসেসিং, টার্টল, ডিস্ট-প্যাকেজ), এটি মডিউল নেমস্পেস থেকে "একক-আন্ডারস্কোর" ব্যক্তিগত "ফাংশনগুলি" আড়াল "করতে ব্যবহৃত হয়। যদিও এর ব্যবহারটি কয়েকটি কয়েকটি মডিউলে খুব বেশি কেন্দ্রীভূত হয় - সম্ভবত এটি ইঙ্গিত দেয় যে এটি মূলত একটি স্টাইলিস্টিক জিনিস। যদিও আমি এর কোনও উদাহরণ পাই না, তবে @staticmethodআপনার কোডটি সাবক্লাসগুলি ওভারডেয়েবল হয়ে সাজাতে সহায়তা করতে পারে। এটি ছাড়া আপনার ফাংশনের রূপগুলি মডিউল নেমস্পেসের চারপাশে ভাসমান।
unutbu

14
... উদাহরণস্বরূপ, শ্রেণি বা স্থির পদ্ধতিগুলি কোথায় এবং কেন ব্যবহার করতে হবে সে সম্পর্কে কিছু ব্যাখ্যা সহ । আপনি এ সম্পর্কে একটি শব্দও দেননি, তবে ওপিও এ সম্পর্কে জিজ্ঞাসা করেনি।
MestreLion

106
@ অ্যালকোট: আনটবু যেমন বলেছিলেন, স্থির পদ্ধতিগুলি একটি সংস্থা / শৈলীগত বৈশিষ্ট্য। কখনও কখনও মডিউলটির অনেকগুলি ক্লাস থাকে এবং কিছু সহায়ক ফাংশন যুক্তিযুক্তভাবে এ এ প্রদত্ত শ্রেণীর সাথে আবদ্ধ হয় এবং অন্যের সাথে নয়, সুতরাং এটি অনেকগুলি "ফ্রি ফাংশন" দিয়ে মডিউলটিকে "দূষিত" না করার অর্থ দেয় এবং স্ট্যাটিক ব্যবহার করা ভাল is কোডগুলিতে মিশ্রণ ক্লাস এবং ফাংশন ডিএফগুলির একসাথে দুর্বল স্টাইলের উপর নির্ভর করার চেয়ে কেবল তারা "সম্পর্কিত" দেখানোর জন্য
মস্ট্র্রেলিয়ন

4
এর জন্য আরও একটি ব্যবহার @staticmethod- আপনি ক্রাফ্ট অপসারণ করতে এটি ব্যবহার করতে পারেন। আমি পাইথনে একটি প্রোগ্রামিং ল্যাঙ্গুয়েজ বাস্তবায়ন করছি - গ্রন্থাগার-সংজ্ঞায়িত ফাংশনগুলি একটি স্থির executeপদ্ধতি ব্যবহার করে , যেখানে ব্যবহারকারী-সংজ্ঞায়িত ফাংশনগুলিতে উদাহরণ যুক্তি (যেমন ফাংশন বডি) প্রয়োজন require এই সাজসজ্জারটি পাইচর্ম পরিদর্শকের "অব্যবহৃত প্যারামিটার স্ব" সতর্কতাগুলি সরিয়ে দেয়।
তেহওয়ালরাস

798

একটি স্ট্যাটিকমেডোথ এমন একটি পদ্ধতি যা এটির শ্রেণি বা উদাহরণ সম্পর্কে কিছুই জানে না on এটি কেবল আর্গুমেন্টগুলি পেয়েছিল যা কোনও উত্তীর্ণ প্রথম যুক্তি নয়। এটি পাইথনের মূলত অকেজো - আপনি একটি স্ট্যাটিকমেথডের পরিবর্তে একটি মডিউল ফাংশন ব্যবহার করতে পারেন।

অন্যদিকে , একটি শ্রেণিবদ্ধ একটি পদ্ধতি যেটিকে যে ক্লাসটি বলা হয়েছিল তা পাস হয় বা প্রথম যুক্তি হিসাবে এটি যে শ্রেণীর নামে ডাকা হত। আপনি যখন পদ্ধতিটি ক্লাসের জন্য একটি কারখানা হতে চান তখন এটি কার্যকর হয়: যেহেতু এটি আসল শ্রেণিটি পায় এটি প্রথম যুক্তি হিসাবে বলা হয়েছিল, আপনি সাবক্লাসগুলি জড়িত থাকা সত্ত্বেও সর্বদা সঠিক বর্গকে ইনস্ট্যান্ট করতে পারেন। উদাহরণস্বরূপ পর্যবেক্ষণ করুন dict.fromkeys(), কীভাবে একটি শ্রেণিবদ্ধ, সাবক্লাসে ডাকলে সাবক্লাসের কোনও উদাহরণ দেয়:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

712
একটি স্ট্যাটিকমেথড অকেজো নয় - এটি কোনও শ্রেণিতে কোনও ফাংশন স্থাপন করার একটি উপায় (কারণ এটি যুক্তিযুক্তভাবে সেখানে রয়েছে) এটি নির্দেশ করে যে এটির জন্য শ্রেণিতে অ্যাক্সেসের প্রয়োজন নেই।
টনি মায়ার

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

40
শ্রেণীর অভ্যন্তরে কোনও পদ্ধতি সংজ্ঞায়িত করার বিষয়ে কী যুক্তিযুক্ত, যখন শ্রেণীর সাথে বা এর উদাহরণগুলির সাথে কোনও সম্পর্ক নেই?
বেন জেমস

106
সম্ভবত উত্তরাধিকারের জন্য? স্ট্যাটিক পদ্ধতিগুলি যেমন উত্তরাধিকার সূত্রে প্রাপ্ত এবং উদাহরণস্বরূপ পদ্ধতি এবং শ্রেণিক পদ্ধতিগুলির মতো ওভাররাইড করা যায় এবং চেহারাটি প্রত্যাশার মতো কাজ করে (জাভা হিসাবে নয়)। স্থির পদ্ধতিগুলি ক্লাস বা উদাহরণস্বরূপ বলা হয় কিনা তা স্থিতিশীলভাবে সমাধান করা হয় না, সুতরাং শ্রেণি এবং স্থির পদ্ধতির মধ্যে একমাত্র পার্থক্য হ'ল প্রথম যুক্তি।
haridsv

80
তারা একটি ক্লিনার নামস্থানও তৈরি করে এবং শ্রেণীর সাথে কিছু করার জন্য ফাংশনটি বোঝা সহজ করে তোলে।
Imbrondir

149

মূলত এমন @classmethodএকটি পদ্ধতি তৈরি করে যার প্রথম আর্গুমেন্টটি তাকে শ্রেণীর বলা হয় (শ্রেণীর উদাহরণের চেয়ে), এতে @staticmethodকোনও অন্তর্নিহিত যুক্তি নেই।


103

অফিসিয়াল পাইথন ডক্স:

@classmethod

কোনও শ্রেণি পদ্ধতি যেমন প্রথম উদাহরণ হিসাবে উদাহরণটি গ্রহণ করে ঠিক তেমন প্রথম যুক্তি হিসাবে ক্লাস গ্রহণ করে। একটি শ্রেণিবদ্ধ পদ্ধতি ঘোষণা করতে, এই প্রতিমাটি ব্যবহার করুন:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

@classmethodফর্ম একটি ফাংশন প্রসাধক - ফাংশন সংজ্ঞা বিবরণ দেখুন ফাংশন সংজ্ঞা বিস্তারিত জানার জন্য।

এটি ক্লাসে (যেমন C.f()) বা কোনও উদাহরণে (যেমন C().f()) বলা যেতে পারে । উদাহরণটি এর শ্রেণি ব্যতীত উপেক্ষা করা হবে। যদি একটি শ্রেণিবদ্ধ পদ্ধতিকে ডেরিভড শ্রেণীর জন্য ডাকা হয়, তবে উত্পন্ন প্রথম শ্রেণীর আর্গুমেন্ট হিসাবে উত্পন্ন ক্লাস অবজেক্টটি পাস করা হয়।

শ্রেণিক পদ্ধতিগুলি সি ++ বা জাভা স্ট্যাটিক পদ্ধতির চেয়ে পৃথক। যদি আপনি এটি চান, staticmethod()এই বিভাগে দেখুন।

@staticmethod

একটি স্থিতিশীল পদ্ধতি একটি অন্তর্নিহিত প্রথম যুক্তি গ্রহণ করে না। একটি স্থিতিশীল পদ্ধতি ঘোষণা করতে, এই প্রতিমাটি ব্যবহার করুন:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

@staticmethodফর্ম একটি ফাংশন প্রসাধক - ফাংশন সংজ্ঞা বিবরণ দেখুন ফাংশন সংজ্ঞা বিস্তারিত জানার জন্য।

এটি ক্লাসে (যেমন C.f()) বা কোনও উদাহরণে (যেমন C().f()) বলা যেতে পারে । উদাহরণটি এর শ্রেণি ব্যতীত উপেক্ষা করা হবে।

পাইথনের স্ট্যাটিক পদ্ধতি জাভা বা সি ++ এর মতো পাওয়া যায়। আরও উন্নত ধারণার classmethod()জন্য এই বিভাগে দেখুন।


ডক্সে কোনও ত্রুটি নেই? স্থিতিশীল হওয়া উচিত নয়: "উদাহরণ এবং এর শ্রেণি উভয়ই উপেক্ষা করা হয়েছে।" পরিবর্তে "উদাহরণটি তার শ্রেণি ব্যতীত উপেক্ষা করা হবে?"
মিরেক

এটি একটি কাটা এবং পেস্ট ত্রুটি হতে পারে, তবে কঠোরভাবে বলতে গেলে আপনি ক্লাসটিকে উপেক্ষা করলে কোনও শ্রেণিতে কোনও পদ্ধতিতে কল করতে পারবেন না।
অ্যারন বেন্টলে

76

এই প্রশ্নের একটি সংক্ষিপ্ত নিবন্ধ এখানে

@ স্ট্যাটিকমেডোথ ফাংশন কোনও শ্রেণীর ভিতরে সংজ্ঞায়িত ফাংশন ছাড়া আর কিছুই নয়। এটি ক্লাসে প্রথমে তাত্ক্ষণিক না করে কলযোগ্য। উত্তরাধিকারের মাধ্যমে এর সংজ্ঞাটি পরিবর্তনযোগ্য।

ক্লাসমেডোথড ফাংশন ক্লাসটি ইনস্ট্যান্ট না করেও কল করা যায় তবে এর সংজ্ঞা উত্তরাধিকারের মাধ্যমে প্যারেন্ট ক্লাস নয়, সাব ক্লাস অনুসরণ করে। কারণ ক্লাসমেডোথড ফাংশনটির জন্য প্রথম যুক্তিটি সর্বদা ক্লাস (শ্রেণি) হওয়া উচিত।


1
তাহলে এর অর্থ কি এই যে কোনও স্ট্যাটিকডেমোথড ব্যবহার করে আমি সর্বদা পিতামাতার ক্লাসের সাথে আবদ্ধ এবং শ্রেণীবদ্ধের সাথে আমি যে শ্রেণিতে আমি ক্লাসমেডকে ঘোষনা করি (এই ক্ষেত্রে সাব বর্গ)?
মোহন গুলতি

7
না। একটি স্ট্যাটিকমেথড ব্যবহার করে আপনি মোটেই আবদ্ধ নন; কোনও অন্তর্নিহিত প্রথম প্যারামিটার নেই। ক্লাসমেডোথ ব্যবহার করে আপনি প্রথমে যে পদ্ধতিটিকে পদ্ধতিটি বলেছিলেন সেটিকে প্রথম শ্রেণীর প্যারামিটার হিসাবে (যদি আপনি এটি সরাসরি কোনও ক্লাসে ডেকে থাকেন), বা যে পদ্ধতিটির জন্য আপনি পদ্ধতিটি কল করেছিলেন (যদি আপনি এটি কোনও উদাহরণে ডাকেন) get
ম্যাট অ্যান্ডারসন

6
এটি দেখানোর জন্য কিছুটা প্রসারিত করা যেতে পারে, প্রথম যুক্তি হিসাবে শ্রেণি রেখে শ্রেণিবদ্ধ পদ্ধতিগুলির মধ্যে অন্যান্য শ্রেণীর বৈশিষ্ট্য এবং পদ্ধতিগুলির মধ্যে সরাসরি অ্যাক্সেস থাকে, যখন স্থির পদ্ধতিগুলি হয় না (এটির জন্য তাদের মাইক্লাস.এইচটি হার্ডকোড করা দরকার)
ম্যাস্ট্রিলিয়ন

"উত্তরাধিকারের মাধ্যমে এর সংজ্ঞাটি পরিবর্তনযোগ্য" " পাইথনে কোনও অর্থবোধ করে না, আপনি একটি স্থিতিশীল পদ্ধতিটিকে ঠিক সূক্ষ্মভাবে ওভাররাইড করতে পারেন।
সিজেড

68

@ স্ট্যাটিকমেডোথ বা @ ক্ল্যাসমেডথোড ব্যবহার করবেন কিনা তা সিদ্ধান্ত নেওয়ার জন্য আপনাকে আপনার পদ্ধতির ভিতরে দেখতে হবে। যদি আপনার পদ্ধতিটি আপনার ক্লাসে অন্যান্য ভেরিয়েবল / পদ্ধতিতে অ্যাক্সেস করে তবে ক্লাসমেডথ ব্যবহার করুন । অন্যদিকে, যদি আপনার পদ্ধতিটি ক্লাসের অন্য কোনও অংশে স্পর্শ না করে তবে @ স্ট্যাটিকমেডথ ব্যবহার করুন।

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1

কি এবং classmethod এবং cls._counter বনাম staticmethod সুবিধা হবে Apple._counter
রবার্ট নোওয়াক

1
cls._countercls._counterকোডটি অন্য কোনও ক্লাসে রাখা হলেও, বা শ্রেণীর নাম পরিবর্তন করা গেলেও তা হবে । শ্রেণীর Apple._counterজন্য নির্দিষ্ট Apple; ভিন্ন শ্রেণীর জন্য, বা শ্রেণীর নাম পরিবর্তন করা হলে আপনাকে রেফারেন্সযুক্ত শ্রেণিটি পরিবর্তন করতে হবে।
কিমলালুনো

52

পাইথনে @ স্ট্যাটিকমেডোথ এবং @ ক্লাসমেডোথের মধ্যে পার্থক্য কী?

আপনি এই সিডোকোডের মতো পাইথন কোডটি দেখে থাকতে পারেন, যা বিভিন্ন পদ্ধতির ধরণের স্বাক্ষরগুলি প্রদর্শন করে এবং প্রতিটি ব্যাখ্যা করার জন্য একটি ডক্টস্ট্রিং সরবরাহ করে:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

সাধারন উদাহরণ পদ্ধতি

প্রথমে আমি ব্যাখ্যা করব a_normal_instance_method। এটিকে অবিকল একটি " উদাহরণ পদ্ধতি " বলা হয়। যখন একটি উদাহরণ পদ্ধতি ব্যবহার করা হয়, এটি আংশিক ফাংশন হিসাবে ব্যবহৃত হয় (উত্স কোডে দেখা যায় যখন সমস্ত মানগুলির জন্য সংজ্ঞায়িত মোট ফাংশনের বিপরীতে), যখন ব্যবহৃত হয়, আর্গুমেন্টের প্রথমটি পূর্বরূপ হিসাবে সংজ্ঞায়িত করা হয় বস্তু, তার প্রদত্ত সমস্ত বৈশিষ্ট্য সহ। এটিতে আবদ্ধ বস্তুর উদাহরণ রয়েছে এবং এটি অবশ্যই অবজেক্টের উদাহরণ থেকে কল করা উচিত। সাধারণত এটি উদাহরণের বিভিন্ন বৈশিষ্ট্য অ্যাক্সেস করবে।

উদাহরণস্বরূপ, এটি একটি স্ট্রিংয়ের উদাহরণ:

', '

যদি আমরা joinএই স্ট্রিংটিতে উদাহরণ পদ্ধতিটি ব্যবহার করি , তবে অন্য পুনরাবৃত্তিতে যোগদানের জন্য এটি অবশ্যই স্পষ্টতই উদাহরণস্বরূপ একটি কাজ যা পুনরাবৃত্তিযোগ্য তালিকার ফাংশন ছাড়াও ['a', 'b', 'c']:

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

বাউন্ড পদ্ধতি

ইনস্ট্যান্স পদ্ধতিগুলি পরে ব্যবহারের জন্য বিন্দুযুক্ত লুকের মাধ্যমে আবদ্ধ হতে পারে।

উদাহরণস্বরূপ, এটি str.joinপদ্ধতির সাথে উদাহরণটিকে আবদ্ধ করে ':':

>>> join_with_colons = ':'.join 

এবং পরে আমরা এটি একটি ফাংশন হিসাবে ব্যবহার করতে পারি যা ইতিমধ্যে এটির সাথে প্রথম যুক্তি আবদ্ধ। এইভাবে, এটি উদাহরণে একটি আংশিক ফাংশনের মতো কাজ করে:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

স্থির পদ্ধতি

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

এটি একটি মডিউল স্তর ফাংশনের সাথে খুব মিল।

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

যদি এটি কোনও বস্তুর সাথে সংযুক্ত থাকে তবে এটি আমদানি এবং উত্তরাধিকারের মাধ্যমেও অবজেক্টটি সুবিধামত অনুসরণ করবে।

একটি স্ট্যাটিক পদ্ধতি একটি উদাহরণ str.maketrans, থেকে সরানো stringমডিউল পাইথন 3 এটা দ্বারা খরচ একটি অনুবাদ টেবিল উপযুক্ত করে তোলে str.translate। এটি স্ট্রিংয়ের উদাহরণ থেকে ব্যবহার করার সময় নিখুঁত বলে মনে হচ্ছে যেমন নীচে প্রদর্শিত হয়েছে, তবে stringমডিউল থেকে ফাংশনটি আমদানি করা বরং আনাড়ি, এবং ক্লাস থেকে এটি কল করতে সক্ষম হওয়ায় এটি খুব ভাল nicestr.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

পাইথন 2 এ, আপনাকে ক্রমবর্ধমান কম কার্যকর স্ট্রিং মডিউল থেকে এই ফাংশনটি আমদানি করতে হবে:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

ক্লাস পদ্ধতি

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

একটি অন্তর্নির্মিত শ্রেণিবদ্ধের সর্বাধিক বিভক্ত উদাহরণ dict.fromkeys। এটি ডিকের বিকল্প নির্মাতা হিসাবে ব্যবহৃত হয়, (আপনার কীগুলি কী এবং যখন আপনি এটির জন্য একটি ডিফল্ট মান চান তখন আপনার পক্ষে উপযুক্ত)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

যখন আমরা ডক সাবক্লাস করি, আমরা একই কন্সট্রাক্টর ব্যবহার করতে পারি, যা সাবক্লাসের একটি উদাহরণ তৈরি করে।

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

দেখুন পান্ডাস সোর্স কোড বিকল্প কনস্ট্রাকটর অন্যান্য অনুরূপ উদাহরণের জন্য, এবং এছাড়াও অফিসিয়াল পাইথন ডকুমেন্টেশন দেখুন classmethodএবং staticmethod


42

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

শ্রেণি পদ্ধতি: জাভা এবং সি ++ এর বিপরীতে পাইথনটিতে কনস্ট্রাক্টর ওভারলোডিং নেই। এবং তাই এটি অর্জন করতে আপনি ব্যবহার করতে পারেন classmethod। নিম্নলিখিত উদাহরণ এটি ব্যাখ্যা করবে

এর বিবেচনা আমরা করি Personবর্গ যা দুটি আর্গুমেন্ট লাগে first_nameএবং last_nameএবং উদাহরণস্বরূপ সৃষ্টি Person

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

এখন, যদি প্রয়োজনীয়তাটি আসে যেখানে আপনাকে কেবলমাত্র একটি একক নাম ব্যবহার করে একটি ক্লাস তৈরি করতে হবে first_name, আপনি পাইথনে এই জাতীয় কিছু করতে পারবেন না

আপনি যখন কোনও অবজেক্ট (উদাহরণ) তৈরি করার চেষ্টা করবেন তখন এটি আপনাকে একটি ত্রুটি দেয়।

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

তবে, আপনি @classmethodনীচে উল্লিখিত হিসাবে একই জিনিস অর্জন করতে পারে

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

স্থিতিশীল পদ্ধতি: এটি বরং সহজ, এটি উদাহরণ বা শ্রেণীর জন্য আবদ্ধ নয় এবং আপনি কেবল শ্রেণীর নাম ব্যবহার করে এটি কল করতে পারেন।

সুতরাং আসুন উপরের উদাহরণে আপনাকে এমন একটি বৈধতা প্রয়োজন যা first_name20 টি অক্ষরের বেশি হওয়া উচিত নয়, আপনি কেবল এটি করতে পারেন।

@staticmethod  
def validate_name(name):
    return len(name) <= 20

এবং আপনি কেবল ব্যবহার করে কল করতে পারেন class name

Person.validate_name("Gaurang Shah")

2
এটি একটি পুরাতন পোস্ট, তবে এক বা দুটি যুক্তি গ্রহণকারী কনস্ট্রাক্টর অর্জনের আরও def __init__(self, first_name, last_name="")অজগর উপায়টি শ্রেণিবদ্ধের পরিবর্তে ব্যবহার করা হবে get_person। এছাড়াও ফলাফল এক্ষেত্রে ঠিক একই হবে।
আকারিলিমানো

31

আমার মনে হয় এর থেকে আরও ভাল প্রশ্ন "আপনি কখন ক্লাসমেডোথ বনাম @ স্ট্যাটিকমেডোথ ব্যবহার করবেন?"

@ ক্লাসমেডোড আপনাকে শ্রেণীর সংজ্ঞার সাথে সম্পর্কিত ব্যক্তিগত সদস্যদের সহজে অ্যাক্সেসের অনুমতি দেয়। এটি সিঙ্গলেটন করার দুর্দান্ত উপায় বা কারখানার ক্লাস যা তৈরি করা সামগ্রীর সংখ্যার নিয়ন্ত্রণ করে।

@ স্ট্যাটিকমোথড প্রান্তিক পারফরম্যান্স লাভ সরবরাহ করে তবে আমি এখনও ক্লাসের মধ্যে স্থির পদ্ধতির উত্পাদনশীল ব্যবহার দেখতে পেলাম যা শ্রেণীর বাইরে স্ট্যান্ডএল ফাংশন হিসাবে অর্জন করা যায়নি।


31

অজগর ২.৪-এ @ স্বেচ্ছাসেবক যুক্ত করা হয়েছে আপনি যদি অজগর ব্যবহার করেন <2.4 আপনি ক্লাসমেডথ () এবং স্ট্যাটিকমেথড () ফাংশন ব্যবহার করতে পারেন।

উদাহরণস্বরূপ, আপনি যদি কোনও কারখানা পদ্ধতি তৈরি করতে চান (কোন যুক্তি কী হবে তার উপর নির্ভর করে কোনও শ্রেণীর বিভিন্ন প্রয়োগের উদাহরণ ফিরিয়ে ফাংশন) আপনি এই জাতীয় কিছু করতে পারেন:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

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

_is_cluster_forক্লাস্মেথোড পদ্ধতিটি তৈরির আরেকটি সুবিধা হ'ল একটি সাবক্লাস এটির বাস্তবায়ন পরিবর্তন করার সিদ্ধান্ত নিতে পারে, কারণ এটি বেশ জেনারিক এবং একাধিক ধরণের ক্লাস্টার পরিচালনা করতে পারে, তাই কেবল শ্রেণীর নাম পরীক্ষা করা যথেষ্ট নয়।


28

স্থির পদ্ধতি:

  • কোন স্ব তর্ক সঙ্গে সহজ ফাংশন।
  • শ্রেণীর বৈশিষ্ট্যগুলিতে কাজ করা; উদাহরণ বৈশিষ্ট্য নয়।
  • ক্লাস এবং উদাহরণ উভয় মাধ্যমে কল করা যেতে পারে।
  • বিল্ট-ইন ফাংশন স্ট্যাটিকমেডোথ () তাদের তৈরি করতে ব্যবহৃত হয়।

স্থির পদ্ধতির সুবিধা:

  • এটি ক্লাসস্কোপে ফাংশনটির নাম স্থানীয়করণ করে
  • এটি ফাংশন কোডটি যেখানে এটি ব্যবহৃত হচ্ছে তার কাছাকাছি স্থানান্তরিত করে
  • মডিউল স্তরের ফাংশন বনাম আমদানি করার জন্য আরও সুবিধাজনক যেহেতু প্রতিটি পদ্ধতিই বিশেষভাবে আমদানি করতে হয় না

    @staticmethod
    def some_static_method(*args, **kwds):
        pass

শ্রেণি পদ্ধতি:

  • শ্রেণিকাম হিসাবে প্রথম যুক্তিযুক্ত ফাংশন।
  • ক্লাস এবং উদাহরণ উভয় মাধ্যমে কল করা যেতে পারে।
  • এগুলি ক্লাসমেডোথ ইন-বিল্ট ফাংশন দিয়ে তৈরি করা হয়।

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass

22

@staticmethodকেবল পদ্ধতি বর্ণনাকারী হিসাবে ডিফল্ট ফাংশনটি অক্ষম করে। শ্রেণিবদ্ধ আপনার ধারনকে ধারক কলযোগ্যভাবে আবৃত করে যা মালিকের শ্রেণীর রেফারেন্সটিকে প্রথম যুক্তি হিসাবে পাস করে:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

প্রকৃতপক্ষে, classmethodএকটি রানটাইম ওভারহেড রয়েছে তবে এটি নিজস্ব ক্লাসে অ্যাক্সেস করা সম্ভব করে। বিকল্পভাবে আমি একটি মেটাক্লাস ব্যবহার এবং সেই মেটাগ্লাসে ক্লাসের পদ্ধতিগুলি রাখার পরামর্শ দিচ্ছি:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>

1
এটির জন্য আমার সাথে সাথে একটি মেটাক্লাসের সম্ভাব্য অবক্ষয়টি হ'ল এটি হ'ল আপনি উদাহরণস্বরূপ সরাসরি শ্রেণিবদ্ধকে কল করতে পারবেন না। c = C(); c.foo()অ্যাট্রিবিউটআরার উত্থাপন করে, আপনাকে করতে হবে type(c).foo()। এটি একটি বৈশিষ্ট্য হিসাবেও বিবেচিত হতে পারে - আপনি কেন চাইবেন তা আমি ভাবতে পারি না।
অ্যারন হল

20

পাইথনে স্থিতিশীল, শ্রেণি বা বিমূর্ত পদ্ধতি কীভাবে ব্যবহার করতে হবে তার সুনির্দিষ্ট গাইড হ'ল এই বিষয়টির জন্য একটি ভাল লিঙ্ক, এবং নীচের হিসাবে এটির সংক্ষিপ্তসার।

@staticmethodফাংশন একটি শ্রেণীর ভিতরে সংজ্ঞায়িত ফাংশন ছাড়া আর কিছুই নয়। এটি ক্লাসে প্রথমে তাত্ক্ষণিক না করে কলযোগ্য। উত্তরাধিকারের মাধ্যমে এর সংজ্ঞাটি পরিবর্তনযোগ্য।

  • পাইথনকে বস্তুর জন্য একটি বাউন্ড-পদ্ধতি ইনস্ট্যান্ট করতে হবে না।
  • এটি কোডের পঠনযোগ্যতা সহজ করে, এবং এটি নিজেই বস্তুর অবস্থার উপর নির্ভর করে না;

@classmethodক্লাসটি তাত্ক্ষণিকভাবে না করে ফাংশনকে কল করাও যায় তবে এর সংজ্ঞাটি সাব-ক্লাস অনুসরণ করে, প্যারেন্ট ক্লাস নয়, উত্তরাধিকারের মাধ্যমে সাবক্লাসে ওভাররাইড করা যায়। এটা এ কারণে যে জন্য প্রথম যুক্তি @classmethodফাংশন সর্বদা হতে হবে CLS (ক্লাস)।

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

ধন্যবাদ @ জাংডাব - স্থির ফাংশনের উত্তরাধিকারসূত্রে অপরিবর্তনীয়তা মনে হচ্ছে মূল পার্থক্য
হার্ড_কর্ম_আর

18

শুধুমাত্র প্রথম যুক্তি পৃথক :

  • সাধারণ পদ্ধতি: বর্তমান বস্তু যদি স্বয়ংক্রিয়ভাবে একটি (অতিরিক্ত) প্রথম যুক্তি হিসাবে পাস করে
  • শ্রেণিবদ্ধ: বর্তমান অবজেক্টের শ্রেণি স্বয়ংক্রিয়ভাবে একটি অতিরিক্ত (অতিরিক্ত) মুষ্টি আর্গুমেন্ট হিসাবে পাস করা হয়
  • স্থিতিশীল: কোনও অতিরিক্ত যুক্তি স্বয়ংক্রিয়ভাবে পাস করা হয় না। আপনি ফাংশনে যা পাস তা হ'ল আপনি যা পান।

আরো বিস্তারিত...

সাধারণ পদ্ধতি

যখন কোনও বস্তুর পদ্ধতি কল করা হয়, এটি স্বয়ংক্রিয়ভাবে selfতার প্রথম যুক্তি হিসাবে একটি অতিরিক্ত যুক্তি দেওয়া হয় । অর্থাৎ, পদ্ধতি

def f(self, x, y)

অবশ্যই 2 টি যুক্তি সহ কল ​​করা উচিত। selfস্বয়ংক্রিয়ভাবে পাস হয়ে গেছে, এবং এটি নিজেই

বর্গ পদ্ধতি

পদ্ধতিটি সজ্জিত হলে

@classmethod
def f(cls, x, y)

স্বয়ংক্রিয়ভাবে সরবরাহিত যুক্তিটি নয় self , তবে শ্রেণি self

স্থির পদ্ধতি

পদ্ধতিটি সজ্জিত হলে

@staticmethod
def f(x, y)

পদ্ধতিটি মোটেই কোনও স্বয়ংক্রিয় যুক্তি দেওয়া হয় না । এটি কেবলমাত্র যে পরামিতিগুলির সাথে ডাকা হয় তা দেওয়া হয়।

ব্যবহারগুলির

  • classmethod বেশিরভাগ বিকল্প নির্মাণকারীদের জন্য ব্যবহৃত হয়।
  • staticmethodবস্তুর অবস্থা ব্যবহার করে না। এটি কোনও শ্রেণীর বাইরের কোনও ফাংশন হতে পারে। এটি কেবল একই ধরণের কার্যকারিতা সহ গ্রুপিং ফাংশনগুলির জন্য শ্রেণীর ভিতরে রাখে (উদাহরণস্বরূপ, জাভা Mathশ্রেণীর স্থির পদ্ধতিগুলির মতো)
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        """this could be outside the class, but we put it here 
just because we think it is logically related to the class."""
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

16

প্রথমে @ ক্লাসমেডোড বনাম @ স্ট্যাটিকমেডোথের সাথে সজ্জিত কোনও পদ্ধতির মধ্যে সাদৃশ্যটি বলতে পারি।

সাদৃশ্য: কেবলমাত্র ক্লাসের উদাহরণ না দিয়ে উভয়কেই ক্লাসে ডাকা যেতে পারে । সুতরাং, উভয়ই এক অর্থে ক্লাসের পদ্ধতি

পার্থক্য: একজন শ্রেণিবদ্ধ নিজেই প্রথম যুক্তি হিসাবে শ্রেণিটি গ্রহণ করবে, যখন কোনও স্ট্যাটিকমেডর নেই।

সুতরাং একটি স্থিতিশীল পদ্ধতিটি এক অর্থে ক্লাসের সাথে আবদ্ধ নয় এবং কেবল সেখানে ঝুলছে কেবল কারণ এটির একটি সম্পর্কিত কার্যকারিতা থাকতে পারে।

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

11

স্ট্যাটিসমেডোড বনাম ক্লাসমেডোথের বিষয়ে আরেকটি বিবেচনা উত্তরাধিকার নিয়ে আসে। বলুন যে আপনি নিম্নলিখিত ক্লাস আছে:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

এবং তারপরে bar()আপনি একটি শিশু শ্রেণিতে ওভাররাইড করতে চান :

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

এটি কাজ করে, তবে মনে রাখবেন যে এখন bar()শিশু শ্রেণিতে প্রয়োগকরণ ( Foo2) আর এই শ্রেণীর নির্দিষ্ট কোনও কিছুর সুবিধা নিতে পারে না। উদাহরণস্বরূপ, বলুন Foo2এর একটি পদ্ধতি ছিল magic()যা আপনি Foo2প্রয়োগের ক্ষেত্রে ব্যবহার করতে চান bar():

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

কার্যসংক্রান্ত এখানে ডাকতে হবে Foo2.magic()মধ্যে bar(), কিন্তু তারপর আপনি নিজেকে পুনরাবৃত্তি করছি (যদি নাম Foo2পরিবর্তন, আপনি যে আপডেট করার জন্য মনে রাখা হবে bar()পদ্ধতি)।

আমার কাছে এটি উন্মুক্ত / বদ্ধ নীতিটির সামান্য লঙ্ঘন , যেহেতু একটি সিদ্ধান্ত গৃহীত Fooশ্রেণীর (সাধারণভাবে এটি সম্প্রসারণে কম উন্মুক্ত) সাধারণ কোডটি রিফ্যাক্টর করার ক্ষমতাকে প্রভাবিত করছে since যদি bar()একটি ছিল classmethodআমরা ভালো হতে চাই:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

দেয়: In Foo2 MAGIC


7

আমি একটি উদাহরণ ব্যবহার করে মূল পার্থক্য ব্যাখ্যা করার চেষ্টা করব।

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - আমরা সরাসরি আরম্ভ না করে স্ট্যাটিক এবং শ্রেণিবদ্ধদের কল করতে পারি

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- স্ট্যাটিক পদ্ধতি স্ব পদ্ধতিটি কল করতে পারে না তবে অন্যান্য স্থিতিশীল এবং শ্রেণিবদ্ধকেও কল করতে পারে

3- স্থিতিশীল পদ্ধতি শ্রেণীর অন্তর্গত এবং কোনও কিছুই অবজেক্ট ব্যবহার করবে না।

4- শ্রেণি পদ্ধতি কোনও বস্তুর সাথে আবদ্ধ নয় তবে একটি শ্রেণীর কাছে আবদ্ধ।


বিজ্ঞাপন 2: আপনি কি নিশ্চিত? স্ট্যাটিকমথার কীভাবে ক্লাসমেডোথ বলতে পারেন? এটির (এর শ্রেণিতে) কোনও রেফারেন্স নেই।
মিরেক

7

@ ক্লাসমেডোথ: এই শ্রেণীর তৈরি সমস্ত দৃষ্টান্তগুলিতে একটি ভাগ করে নেওয়া বিশ্বব্যাপী অ্যাক্সেস তৈরি করতে ব্যবহার করা যেতে পারে ..... একাধিক ব্যবহারকারী দ্বারা রেকর্ড আপডেট করার মতো .... আমি বিশদ বিবরণটি সিলেটলেট তৈরি করার সময় এটি সম্পূর্ণরূপে ব্যবহার করতে দেখেছি ..: )

@ স্ট্যাটিক পদ্ধতি: শ্রেণি বা উদাহরণের সাথে সম্পর্কিত হওয়ার সাথে কিছুই করার নেই ... তবে পাঠযোগ্যতার জন্য স্থিতিশীল পদ্ধতি ব্যবহার করতে পারেন


5

আপনি এর মধ্যে পার্থক্যটি বিবেচনা করতে চাইতে পারেন:

Class A:
    def foo():  # no self parameter, no decorator
        pass

এবং

Class B:
    @staticmethod
    def foo():  # no self parameter
        pass

এটি পাইথন 2 এবং পাইথন 3 এর মধ্যে পরিবর্তিত হয়েছে:

python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

সুতরাং @staticmethodক্লাস থেকে সরাসরি ডাকা পদ্ধতিগুলির জন্য অজগর 3 এ alচ্ছিক হয়ে উঠেছে। আপনি যদি তাদের ক্লাস এবং উদাহরণ উভয় থেকে কল করতে চান তবে আপনাকে এখনও @staticmethodডেকোরেটর ব্যবহার করতে হবে ।

অন্যান্য মামলাগুলি আনটবাস উত্তরের দ্বারা ভালভাবে কভার করা হয়েছে।


4

আমার অবদান মাঝে পার্থক্য প্রমান @classmethod, @staticmethodকিভাবে একটি দৃষ্টান্ত পরোক্ষভাবে একটি কল করতে পারেন সহ, এবং উদাহরণ হিসেবে বলা যায় পদ্ধতি, @staticmethod। তবে @staticmethodকোনও উদাহরণ থেকে অপ্রত্যক্ষভাবে ফোন করার পরিবর্তে এটিকে ব্যক্তিগত করা আরও "পাইথোনিক" হতে পারে। একটি ব্যক্তিগত পদ্ধতি থেকে কিছু পাওয়া এখানে প্রদর্শিত হয় না তবে এটি মূলত একই ধারণা।

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""

4

কোনও শ্রেণি পদ্ধতি যেমন প্রথম উদাহরণ হিসাবে উদাহরণটি গ্রহণ করে ঠিক তেমন প্রথম যুক্তি হিসাবে ক্লাস গ্রহণ করে। এটি এমন একটি পদ্ধতি যা ক্লাসের সাথে আবদ্ধ এবং ক্লাসের অবজেক্ট নয় t এটি ক্লাসের স্থিতিতে অ্যাক্সেস পায় কারণ এটি ক্লাসের প্যারামিটার নেয় যা শ্রেণীর দিকে নির্দেশ করে এবং বস্তুর উদাহরণ নয়। এটি এমন একটি শ্রেণীর রাষ্ট্র পরিবর্তন করতে পারে যা শ্রেণীর সমস্ত দৃষ্টান্ত জুড়ে প্রযোজ্য। উদাহরণস্বরূপ এটি শ্রেণীর পরিবর্তনশীলটি সংশোধন করতে পারে যা সমস্ত দৃষ্টান্তের জন্য প্রযোজ্য।

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

গাইডলাইন হিসাবে, ইউটিলিটি হিসাবে স্থির পদ্ধতি ব্যবহার করুন, উদাহরণস্বরূপ কারখানা হিসাবে শ্রেণিবদ্ধ পদ্ধতি ব্যবহার করুন। অথবা হতে পারে একটি একক সংজ্ঞা দিতে। এবং দৃষ্টান্তগুলির স্টেট এবং আচরণের মডেল করতে উদাহরণ পদ্ধতিগুলি ব্যবহার করুন।

আশা করি আমি পরিষ্কার ছিলাম!


2

ক্লাসের পদ্ধতিগুলি যেমন নাম অনুসারে বোঝায়, ক্লাসে পরিবর্তন করতে ব্যবহৃত হয় না বস্তুগুলিতে। ক্লাসে পরিবর্তন করতে, তারা শ্রেণীর বৈশিষ্ট্যগুলি পরিবর্তন করবে (অ্যাট্রিবিউট বৈশিষ্ট্য নয়), যেহেতু আপনি ক্লাসগুলি আপডেট করেন। এই কারণেই শ্রেণি পদ্ধতিগুলি প্রথম যুক্তি হিসাবে শ্রেণিবদ্ধ করে (প্রচলিতভাবে 'ক্লস' দ্বারা চিহ্নিত) take

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

অন্যদিকে স্থিতিশীল পদ্ধতিগুলি কার্যকারিতা সম্পাদনের জন্য ব্যবহৃত হয় যা শ্রেণীর সাথে আবদ্ধ নয় তারা শ্রেণি ভেরিয়েবলগুলি পড়বে না বা লেখবে না। সুতরাং, স্থিতিশীল পদ্ধতিগুলি আর্গুমেন্ট হিসাবে ক্লাস নেয় না। এগুলি ব্যবহার করা হয় যাতে ক্লাসগুলি ক্রিয়াকলাপগুলি সম্পাদন করতে পারে যা শ্রেণীর উদ্দেশ্যগুলির সাথে সরাসরি সম্পর্কিত নয়।

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."

2

আক্ষরিক অর্থে @staticmethod বিশ্লেষণ করুন বিভিন্ন অন্তর্দৃষ্টি সরবরাহ করে ।

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

একটি স্ট্যাটিকমোথড প্রকৃতপক্ষে একটি সাধারণ ফাংশন যা শ্রেণীর সংজ্ঞার বাইরে থাকে।
ভাগ্যক্রমে ক্লাসে এটি শ্রেণিবদ্ধ করা হয়েছে যেখানে এটি প্রয়োগ করা হয় সেখানে আরও দাঁড়ানোর জন্য, অথবা আপনি এটি সন্ধান করতে প্রায় স্ক্রোল করতে পারেন।


2

আমি মনে করি staticmethodএবং এর খাঁটি পাইথন সংস্করণ দিচ্ছিclassmethod ভাষা পর্যায়ে তাদের মধ্যে পার্থক্য বুঝতে সাহায্য করবে।

উভয়ই ডেটাবিহীন বর্ণনাকারী (যদি আপনি পরিচিত হন তবে এগুলি বোঝা আরও সহজ হবে প্রথমে বর্ণনাকারীদের )।

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

1

উত্তরাধিকার শ্রেণিবিন্যাসে স্থিতিযুক্তের কোনও অবজেক্টের, শ্রেণীর বা পিতামাতার শ্রেণীর অ্যাটটিবাইটের অ্যাক্সেস নেই। এটি ক্লাসে সরাসরি বলা যেতে পারে (কোনও বস্তু তৈরি না করে)।

শ্রেণীবদ্ধের অবজেক্টের বৈশিষ্ট্যে অ্যাক্সেস নেই। এটি অবশ্য উত্তরাধিকারক্রমক্রমের শ্রেণিতে এবং পিতামাতার শ্রেণীর বৈশিষ্ট্যগুলিতে অ্যাক্সেস করতে পারে। এটি ক্লাসে সরাসরি বলা যেতে পারে (কোনও বস্তু তৈরি না করে)। যদি বস্তুটিতে ডাকা হয় তবে এটি সাধারণ পদ্ধতির মতো যা অ্যাক্সেস করে না self.<attribute(s)>এবং self.__class__.<attribute(s)>কেবল অ্যাক্সেস করে না ।

ভাবুন আমাদের একটি ক্লাস রয়েছে b=2, আমরা একটি অবজেক্ট তৈরি করব b=4এবং এটিতে এটি পুনরায় সেট করব । স্ট্যাটিকমেডোস্ট পূর্বের কিছুই অ্যাক্সেস করতে পারে না। ক্লাসমেডুড .b==2কেবলমাত্র, মাধ্যমে অ্যাক্সেস করতে পারে cls.b। সাধারণ পদ্ধতি উভয় .b==4মাধ্যমে self.bএবং .b==2মাধ্যমে অ্যাক্সেস করতে পারেself.__class__.b

আমরা কেআইএসএস স্টাইলটি অনুসরণ করতে পারি (এটি সহজ, বোকা রাখুন): স্ট্যাটিকমেডথ এবং শ্রেণীবদ্ধগুলি ব্যবহার করবেন না, তাত্ক্ষণিকভাবে ক্লাস ব্যবহার করবেন না, কেবলমাত্র অবজেক্টের বৈশিষ্ট্য অ্যাক্সেস করুন self.attribute(s)। এমন ভাষাগুলি রয়েছে যেখানে ওওপিটি সেভাবে কার্যকর করা হয় এবং আমি মনে করি এটি খারাপ ধারণা নয়। :)


শ্রেণীবদ্ধদের কাছে আরও একটি গুরুত্বপূর্ণ বিষয়: আপনি যদি শ্রেণি পদ্ধতিতে কোনও বৈশিষ্ট্য পরিবর্তন করেন তবে এই শ্রেণীর সমস্ত বিদ্যমান বস্তু যা এই বৈশিষ্ট্যটি সুস্পষ্টভাবে সেট করে না সেগুলির পরিবর্তিত মান থাকবে।
মিরেক

-4

আইপাইথনে অন্য দিক থেকে অভিন্ন পদ্ধতি হ্যাক-আপটি প্রকাশ করে যে @staticmethodপ্রান্তিক পারফরম্যান্স লাভ (ন্যানোসেকেন্ডে) লাভ করে, তবে অন্যথায় এটি কোনও কাজ করে না বলে মনে হয়। এছাড়াও, staticmethod()সংকলনের সময় পদ্ধতিটি প্রক্রিয়া করার অতিরিক্ত কাজ দ্বারা কোনও পারফরম্যান্স লাভ সম্ভবত মুছে যাবে (যা আপনি কোনও স্ক্রিপ্ট চালানোর সময় কোনও কোড প্রয়োগের আগে ঘটে) happens

কোড পঠনযোগ্যতার খাতিরে আমি এড়াতে পারি @staticmethodযদি না আপনার পদ্ধতিটি কাজের বোঝার জন্য ব্যবহার করা হয়, যেখানে ন্যানোসেকেন্ডগুলি গণনা করা হয়।


7
"অন্যথায় কোনও ফাংশন পরিবেশন করা হবে বলে মনে হচ্ছে না": কঠোরভাবে সত্য নয়। উপরের আলোচনা দেখুন।
কিথ পিনসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.