শ্রেণি পদ্ধতিগুলির উদ্দেশ্য কী?


250

আমি নিজেকে পাইথন শিখিয়ে দিচ্ছি এবং আমার সাম্প্রতিকতম পাঠটিটি ছিল পাইথন জাভা নয় এবং তাই আমি আমার ক্লাসের সমস্ত পদ্ধতিকে ফাংশনে পরিণত করার জন্য কিছুটা সময় ব্যয় করেছি।

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

পাইথনে ক্লাস পদ্ধতি ব্যবহারের কি কারও কাছে ভাল উদাহরণ রয়েছে বা ক্লাসের পদ্ধতিগুলি বুদ্ধিমানভাবে ব্যবহার করা যেতে পারে এমন সময় সম্পর্কে কেউ আমাকে বলতে পারেন?

উত্তর:


178

শ্রেণি পদ্ধতিগুলি যখন আপনার এমন কোনও পদ্ধতি থাকা দরকার যা কোনও নির্দিষ্ট উদাহরণের সাথে সুনির্দিষ্ট নয় তবে এখনও শ্রেণিটি কোনও উপায়ে জড়িত। তাদের সম্পর্কে সবচেয়ে মজার বিষয় হ'ল এগুলি সাবক্লাস দ্বারা ওভাররাইড করা যেতে পারে, যা জাভা এর স্থির পদ্ধতি বা পাইথনের মডিউল-স্তরের ক্রিয়াকলাপগুলিতে কেবল সম্ভব নয়।

আপনার যদি ক্লাস থাকে MyClassএবং মাইক্লাসে চালিত একটি মডিউল স্তরের ফাংশন (কারখানা, নির্ভরতা ইনজেকশন স্টাব ইত্যাদি) থাকে তবে এটিকে একটি করুন classmethod। তারপরে এটি সাবক্লাসে উপলভ্য হবে।


আমি দেখি. তবে, কীভাবে আমি যদি একটি পদ্ধতিটি কেবল শ্রেণিবদ্ধ করতে চাই, যেটির জন্য মাইক্লাসের প্রয়োজন নেই, তবে এখনও যদি আমি অন্য মাই ক্লাসে গ্রুপ করি তবে কোনও উপায়ে তা বোধগম্য হতে পারে? আমি যদিও এটি সহায়ক মডিউলে স্থানান্তরিত করার কথা ভাবতে পারি ..
swdev

মূল প্রশ্নটির সাথে আমার একটি প্রশ্ন আছে, আপনি কি একই সময়ে উত্তর দিতে পারবেন? কোন বস্তুর শ্রেণিবদ্ধ পদ্ধতিগুলি কল করার কোন উপায়ে "আরও ভাল", বা "আরও মূর্তিমান": obj.cls_mthd(...)বা type(obj).cls_mthd(...)?
আলেক্সি

63

কারখানা পদ্ধতি (বিকল্প নির্মাতারা) প্রকৃতপক্ষে শ্রেণি পদ্ধতির একটি সর্বোত্তম উদাহরণ।

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

উদাহরণ হিসাবে, দুর্দান্ত ইউনিপথ মডিউলে:

বর্তমান ডিরেক্টরি

  • Path.cwd()
    • প্রকৃত বর্তমান ডিরেক্টরিটি ফিরিয়ে দিন; যেমন Path("/tmp/my_temp_dir"),। এটি একটি শ্রেণিবদ্ধ পদ্ধতি।
  • .chdir()
    • বর্তমান ডিরেক্টরিটি তৈরি করুন।

যেহেতু বর্তমান ডিরেক্টরিটি প্রক্রিয়া প্রশস্ত, cwdপদ্ধতিটির কোনও নির্দিষ্ট উদাহরণ নেই যার সাথে এটি যুক্ত হওয়া উচিত। তবে, cwdপ্রদত্ত Pathউদাহরণের ডিরেক্টরিতে ডিরেক্টরি পরিবর্তন করা অবশ্যই একটি উদাহরণ পদ্ধতি হওয়া উচিত should

হুম ... আসলে যেমন Path.cwd()একটি Pathউদাহরণ ফিরে আসে , আমার ধারণা এটি একটি কারখানার পদ্ধতি হিসাবে বিবেচিত হতে পারে ...


1
হ্যাঁ ... কারখানার পদ্ধতিগুলি প্রথম জিনিসটি মনে আসল। এছাড়াও সেই রেখাগুলির পাশাপাশি এমন জিনিস রয়েছে যা সিঙ্গলটনের প্যাটার্নটি বাস্তবায়িত করবে, যেমন: getAndOptionallyCreateSomeSingleInstanceOfSomeResource ()
জেমেনকে

3
পাইথনগুলিতে সেগুলি অবিচলিত পদ্ধতি, শ্রেণিবদ্ধ পদ্ধতি নয়।
জয়কুল

46

এটি এইভাবে চিন্তা করুন: প্রেরণের বিশদটি গোপন করার জন্য সাধারণ পদ্ধতিগুলি দরকারী: পদ্ধতিটি অবজেক্টের শ্রেণি বা এর কোনও অভিভাবক শ্রেণীর দ্বারা প্রয়োগ করা হয়েছে myobj.foo()কিনা তা নিয়ে চিন্তা না করে টাইপ করতে পারেন । শ্রেণি পদ্ধতিগুলি এর সাথে একেবারে সাদৃশ্যযুক্ত, তবে পরিবর্তে শ্রেণীর অবজেক্টের সাথে: তারা বিশেষায়িতভাবে প্রয়োগ করা হয়েছে কিনা তা নিয়ে চিন্তা না করেই আপনি কল করতে পারেন কারণ এটির নিজস্ব বিশেষায়িত সংস্করণ প্রয়োজন, বা এটি তার পিতামাতার ক্লাসটিকে কলটি পরিচালনা করতে দিচ্ছে কিনা।foo()myobjMyClass.foo()foo()MyClass

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

https://github.com/zzzeek/sqlalchemy/blob/ab6946769742602e40fb9ed9dde5f642885d1906/lib/sqlalchemy/dialects/mssql/pymssql.py#L47

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


ভাঙা লিঙ্ক, দয়া করে সামঞ্জস্য করুন
পিয়ারটনি

28

আমি সম্প্রতি খুব হালকা ওজনে লগিং ক্লাস চেয়েছিলাম যা লগিং স্তরের উপর নির্ভর করে বিভিন্ন পরিমাণে আউটপুট আউটপুট তৈরি করতে পারে যা প্রোগ্রামগতভাবে সেট করা যায়। তবে আমি যখনই কোনও ডিবাগিং বার্তা বা ত্রুটি বা সতর্কবার্তা আউটপুট করতে চেয়েছি ক্লাসটি ইনস্ট্যান্ট করতে চাই নি। তবে আমি এই লগিং সুবিধার কার্যকারিতাটি সজ্জিত করে কোনও গ্লোবাল ঘোষণা না করে এটিকে পুনরায় ব্যবহারযোগ্য করে তুলতে চাইছিলাম।

সুতরাং আমি এটি @classmethodঅর্জনের জন্য ক্লাস ভেরিয়েবল এবং ডেকোরেটর ব্যবহার করেছি ।

আমার সাধারণ লগিং ক্লাসের সাথে, আমি নিম্নলিখিতগুলি করতে পারি:

Logger._level = Logger.DEBUG

তারপরে, আমার কোডে, আমি যদি একগুচ্ছ ডিবাগিং তথ্য বের করতে চাই, আমাকে কেবল কোড করতে হয়েছিল

Logger.debug( "this is some annoying message I only want to see while debugging" )

ত্রুটিগুলি সহ করা যেতে পারে

Logger.error( "Wow, something really awful happened." )

"উত্পাদন" পরিবেশে, আমি নির্দিষ্ট করতে পারি

Logger._level = Logger.ERROR

এবং এখন, কেবল ত্রুটি বার্তা আউটপুট হবে। ডিবাগ বার্তা মুদ্রণ করা হবে না।

এখানে আমার ক্লাস:

class Logger :
    ''' Handles logging of debugging and error messages. '''

    DEBUG = 5
    INFO  = 4
    WARN  = 3
    ERROR = 2
    FATAL = 1
    _level = DEBUG

    def __init__( self ) :
        Logger._level = Logger.DEBUG

    @classmethod
    def isLevel( cls, level ) :
        return cls._level >= level

    @classmethod
    def debug( cls, message ) :
        if cls.isLevel( Logger.DEBUG ) :
            print "DEBUG:  " + message

    @classmethod
    def info( cls, message ) :
        if cls.isLevel( Logger.INFO ) :
            print "INFO :  " + message

    @classmethod
    def warn( cls, message ) :
        if cls.isLevel( Logger.WARN ) :
            print "WARN :  " + message

    @classmethod
    def error( cls, message ) :
        if cls.isLevel( Logger.ERROR ) :
            print "ERROR:  " + message

    @classmethod
    def fatal( cls, message ) :
        if cls.isLevel( Logger.FATAL ) :
            print "FATAL:  " + message

এবং কিছু কোড যা এটির সামান্য পরীক্ষা করে:

def logAll() :
    Logger.debug( "This is a Debug message." )
    Logger.info ( "This is a Info  message." )
    Logger.warn ( "This is a Warn  message." )
    Logger.error( "This is a Error message." )
    Logger.fatal( "This is a Fatal message." )

if __name__ == '__main__' :

    print "Should see all DEBUG and higher"
    Logger._level = Logger.DEBUG
    logAll()

    print "Should see all ERROR and higher"
    Logger._level = Logger.ERROR
    logAll()

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

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

3
আপনি কেন একটি স্ট্যাটিকমেথড ব্যবহার করবেন না?
বিডিফোর্বস


10

যখন কোনও ব্যবহারকারী আমার ওয়েবসাইটে লগ ইন করে, কোনও ব্যবহারকারী () অবজেক্টটি ব্যবহারকারীর নাম এবং পাসওয়ার্ড থেকে ইনস্ট্যান্ট করা হয়।

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

আমার ব্যবহারকারীর অবজেক্টটি ধরার জন্য ক্লাস পদ্ধতি রয়েছে।

class User():
    #lots of code
    #...
    # more code

    @classmethod
    def get_by_username(cls, username):
        return cls.query(cls.username == username).get()

    @classmethod
    def get_by_auth_id(cls, auth_id):
        return cls.query(cls.auth_id == auth_id).get()

9

আমি মনে করি সবচেয়ে সুস্পষ্ট উত্তরটি আমানকো এর একটি one আপনি কীভাবে আপনার কোডটি সংগঠিত করতে চান তাতে এটি ফোটে। আপনি মডিউল স্তরের ফাংশন হিসাবে সবকিছু লিখতে পারেন যা মডিউলটির নামস্থানে আবৃত থাকে

module.py (file 1)
---------
def f1() : pass
def f2() : pass
def f3() : pass


usage.py (file 2)
--------
from module import *
f1()
f2()
f3()
def f4():pass 
def f5():pass

usage1.py (file 3)
-------------------
from usage import f4,f5
f4()
f5()

উপরের পদ্ধতিগত কোডটি সুসংগঠিত নয়, আপনি দেখতে পাচ্ছেন কেবল মাত্র 3 টি মডিউল পরে এটি বিভ্রান্ত হয়, প্রতিটি পদ্ধতি কী করে? আপনি ফাংশনগুলির জন্য দীর্ঘ বর্ণনামূলক নামগুলি ব্যবহার করতে পারেন (জাভা হিসাবে) তবে তবুও আপনার কোডটি খুব তাড়াতাড়ি নিয়ন্ত্রণহীন হয়ে পড়ে।

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

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

class FileUtil ():
  def copy(source,dest):pass
  def move(source,dest):pass
  def copyDir(source,dest):pass
  def moveDir(source,dest):pass

//usage
FileUtil.copy("1.txt","2.txt")
FileUtil.moveDir("dir1","dir2")

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


1
F1 (), f2 () ইত্যাদি ব্যবহার করার জন্য, আপনি যেমন করেছেন, আপনার কি মডিউল আমদানি * এবং ব্যবহার আমদানি থেকে ব্যবহার করা উচিত নয়?
Jblasco

@ জাব্লাস্কো বিভ্রান্তি দূর করতে আমি আমদানি বিবৃতি সংশোধন করেছি, হ্যাঁ আপনি যদি মডিউলটি আমদানি করেন তবে আপনাকে মডিউলটির নাম সহ ফাংশনগুলি উপসর্গ করতে হবে। যেমন আমদানি মডিউল -> মডিউল.এফ 1 () ইত্যাদি
ফায়ারফিল

আমি এই উত্তরের সাথে একমত নই; পাইথন জাভা নয়। উদাহরণস্বরূপ দরিদ্র নামগুলি ইচ্ছাকৃত পছন্দ করার কারণে অযৌক্তিক কোডের বিষয়টি কেবল স্পষ্টতই উত্থাপিত হয়েছিল। পরিবর্তে যদি আপনি FileUtilক্লাসের পদ্ধতিগুলি file_utilমডিউলটির ফাংশন হিসাবে প্রতিলিপি করেন তবে তুলনামূলক হবে এবং OOP কে অপব্যবহার করা হবে না যখন আসলে কোনও বস্তু উপস্থিত নেই (আসলে আপনি এটি যুক্তিযুক্ত হতে পারেন, কারণ আপনি from file_util import FileUtilবা অন্য শব্দটির সাথে শেষ না হয়ে )। নামের বিবাদগুলি একইভাবে import file_utilপরিবর্তে পদ্ধতিগত কোডগুলিতে এড়ানো যায় from file_util import ...
ভুলে

7

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

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

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


1
ব্যক্তিগত: _ পরিবর্তনশীল_নাম এবং সুরক্ষিত: __variable_name
ব্র্যাডলি

1
একটি অপরিহার্য ব্যবহার হ'ল ইউনিটেস্টের সেটআপস ক্লাস এবং টিয়ারডাউনক্লাস। আপনি ইউনিটেটস ব্যবহার করছেন, তাই না? :)
ডিবিএন

7

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

উদাহরণ স্বরূপ:

@classmethod
def get_name(cls):
    print cls.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C.get_name()

আপনি যদি ব্যবহার না করেন তবে আপনি @classmethodস্ব কীওয়ার্ড দিয়ে এটি করতে পারেন তবে এটির শ্রেণীর উদাহরণ প্রয়োজন:

def get_name(self):
    print self.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C().get_name() #<-note the its an instance of class C

5

আমি পিএইচপি এর সাথে কাজ করতাম এবং সম্প্রতি আমি নিজেকে জিজ্ঞাসা করছিলাম, এই শ্রেণিবদ্ধের সাথে কী চলছে? পাইথন ম্যানুয়ালটি খুব প্রযুক্তিগত এবং কথায় খুব সংক্ষিপ্ত তাই এটি বৈশিষ্ট্যটি বোঝার জন্য সাহায্য করবে না। আমি গুগল করছি এবং গুগল করছি এবং আমি উত্তর পেয়েছি -> http://code.anjanesh.net/2007/12/python-classmethods.html

আপনি যদি এটি করতে অলস হন। আমার ব্যাখ্যাটি ছোট এবং নীচে। :)

পিএইচপি-তে (সম্ভবত আপনারা সবাই পিএইচপি জানেন না, তবে এই ভাষাটি এত সোজা এগিয়ে রয়েছে যে প্রত্যেকেরই বুঝতে হবে যে আমি কী বলছি) আমাদের স্ট্যাটিক ভেরিয়েবল রয়েছে:


class A
{

    static protected $inner_var = null;

    static public function echoInnerVar()
    {
        echo self::$inner_var."\n";
    }

    static public function setInnerVar($v)
    {
        self::$inner_var = $v;
    }

}

class B extends A
{
}

A::setInnerVar(10);
B::setInnerVar(20);

A::echoInnerVar();
B::echoInnerVar();

ফলাফল দুটি ক্ষেত্রেই হবে।

তবে পাইথনে আমরা @ ক্লাসমেডোড ডেকরেটার যুক্ত করতে পারি এবং এভাবে যথাক্রমে 10 এবং 20 আউটপুট পাওয়া সম্ভব। উদাহরণ:


class A(object):
    inner_var = 0

    @classmethod
    def setInnerVar(cls, value):
        cls.inner_var = value

    @classmethod
    def echoInnerVar(cls):
        print cls.inner_var


class B(A):
    pass


A.setInnerVar(10)
B.setInnerVar(20)

A.echoInnerVar()
B.echoInnerVar()

স্মার্ট, না?


আপনার পাইথনের উদাহরণের সাথে একটি সম্ভাব্য সমস্যা হ'ল যদি এটি B.setInnerVar(20)ছেড়ে চলে যায় তবে এটি 10দু'বার মুদ্রণ করবে (দ্বিতীয় প্রতিধ্বনির বারে ত্রুটি দেওয়ার চেয়ে) কল করুন যে কোনও inner_varসংজ্ঞা দেওয়া হয়নি
মার্টিনো

5

শ্রেণিবদ্ধ পদ্ধতিগুলি একটি "শব্দার্থক চিনি" সরবরাহ করে (এই শব্দটি বহুল ব্যবহৃত হয় কিনা তা জানেন না) - বা "শব্দার্থক সুবিধা"।

উদাহরণ: আপনি বস্তুর প্রতিনিধিত্বমূলক শ্রেণীর একটি সেট পেয়েছেন। আপনার ক্লাস পদ্ধতি থাকতে পারে all()বা find()লিখতে User.all()বা লিখতে হতে পারে User.find(firstname='Guido')। এটি অবশ্যই মডিউল স্তরের ফাংশনগুলি ব্যবহার করে করা যেতে পারে ...


আপনি উদাহরণস্বরূপ অনুমান করেন যে শ্রেণিটি তার সমস্ত দৃষ্টান্ত অনুসরণ করে এবং সেগুলি তৈরি করার পরে সেগুলি অ্যাক্সেস করতে পারে - কিছু স্বয়ংক্রিয়ভাবে সম্পন্ন হয় না।
মার্টিনো

1
"সিনট্যাক্টিক চিনি" "সিনট্যাকটিক সুগার" এর সাথে দুর্দান্ত মিলের মতো শোনাচ্ছে।
এক্সটিএল

3

রুবি থেকে আগত আমাকে কেবল কী আঘাত করেছে, তা হ'ল একটি তথাকথিত শ্রেণি পদ্ধতি এবং তথাকথিত উদাহরণ পদ্ধতিটি তার প্রথম প্যারামিটারে শব্দার্থক অর্থ প্রয়োগ করে কেবল একটি ফাংশন, যা যখন ফাংশনটিকে একটি পদ্ধতি হিসাবে ডাকা হয় তখন নিঃশব্দে পাস হয় a অবজেক্ট (ie obj.meth())।

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

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

এই বিবেচনা:

class Foo():
  def foo(x):
    print(x)

আপনি fooএকটি উদাহরণ কল করতে পারেন

Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>

তবে ক্লাসে নয়:

Foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)

এখন যোগ করুন @classmethod:

class Foo():
  @classmethod
  def foo(x):
    print(x)

একটি উদাহরণে কল করা এখন তার ক্লাসটি কেটে যায়:

Foo().foo()
__main__.Foo

যেমন একটি ক্লাসে কল করে:

Foo.foo()
__main__.Foo

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

রুবির সাথে বৈপরীত্য:

class Foo
  def foo()
    puts "instance method #{self}"
  end
  def self.foo()
    puts "class method #{self}"
  end
end

Foo.foo()
class method Foo

Foo.new.foo()
instance method #<Foo:0x000000020fe018>

পাইথন ক্লাস পদ্ধতিটি কেবল একটি সজ্জিত ফাংশন এবং আপনি নিজের কৌশলগুলি তৈরি করতে একই কৌশল ব্যবহার করতে পারেন । একটি সজ্জিত পদ্ধতি আসল পদ্ধতিটি গুটিয়ে দেয় ( @classmethodএটির ক্ষেত্রে অতিরিক্ত শ্রেণীর যুক্তি পাস হয়) passes অন্তর্নিহিত পদ্ধতিটি এখনও আছে, লুকানো কিন্তু এখনও অ্যাক্সেসযোগ্য


পাদটীকা: আমি একটি ক্লাস এবং উদাহরণ পদ্ধতির মধ্যে নাম সংঘর্ষের পরে আমার কৌতূহল প্রকাশ করে এটি লিখেছিলাম। আমি পাইথন বিশেষজ্ঞ থেকে অনেক দূরে এবং এর মধ্যে কোনওটি ভুল হলে মন্তব্য করতে চাই।


"যা কোনও অবজেক্টের পদ্ধতি হিসাবে ফাংশন বলা হলে নিঃশব্দে পাস হয়" - আমি বিশ্বাস করি এটি সঠিক নয়। আফিক্স, পাইথনে কিছুই "নিঃশব্দে পাস" করা হয় না। আইএমও, পাইথন এই অর্থে রুবির চেয়ে অনেক বেশি বুদ্ধিমান (বাদে super())। আফিক্ট, "ম্যাজিক" ঘটে যখন কোনও অ্যাট্রিবিউট সেট করা বা পড়া হয়। obj.meth(arg)পাইথনে কল (রুবির বিপরীতে) এর অর্থ সহজভাবে (obj.meth)(arg)। কিছুই নিঃশব্দে কোথাও প্রেরণ করা হয় না, obj.methকেবল একটি কলযোগ্য অবজেক্ট যা এটি তৈরি করা ফাংশন থেকে একটি যুক্তি কম গ্রহণ করে।
আলেক্সি

obj.methপরিবর্তে, সহজভাবে মানে getattr(obj, "meth")
আলেক্সি

অন্যান্য সাধারণ ভাষা থেকে আসা লোকদের জন্য একটি উত্তর উপযুক্ত করে তোলে তা বোঝায়। যাইহোক, এই কথোপকথনটি থেকে একটি জিনিস অনুপস্থিত যা এটি একে অপরের সাথে যুক্ত করে, এটি পাইথন বর্ণনাকারীর ধারণা । ফাংশন বর্ণনাকারী , এবং এভাবেই যখন কোনও ফাংশন শ্রেণীর একটি বৈশিষ্ট্য হিসাবে প্রথম আর্গুমেন্ট "স্বয়ংক্রিয়ভাবে" পাস হয় passed শ্রেণিবদ্ধগুলি কীভাবে বাস্তবায়ন করা হয়, এবং আমি যেভাবে সংযুক্ত হউটো তে একটি খাঁটি অজগর বাস্তবায়ন সরবরাহ করা হয়। এটিও একটি সাজসজ্জাবিদ এটি বাস্তব উপকরণ যেমন
juanpa.arrivillaga

2

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

এটি চিত্রিত করার জন্য এখানে একটি উদাহরণ। নোট করুন যে সমস্ত দৃষ্টান্তের একক অভিধানের একটি উল্লেখ রয়েছে। আমি এটি বুঝতে পারি এটি কারখানার ধরণ নয়। এটি অজগরটির পক্ষে সম্ভবত খুব অনন্য।

class M():
 @classmethod
 def m(cls, arg):
     print "arg was",  getattr(cls, "arg" , None),
     cls.arg = arg
     print "arg is" , cls.arg

 M.m(1)   # prints arg was None arg is 1
 M.m(2)   # prints arg was 1 arg is 2
 m1 = M()
 m2 = M() 
 m1.m(3)  # prints arg was 2 arg is 3  
 m2.m(4)  # prints arg was 3 arg is 4 << this breaks the factory pattern theory.
 M.m(5)   # prints arg was 4 arg is 5

2

আমি নিজেকে কয়েকবার একই প্রশ্ন করছিলাম। যদিও এখানকার ছেলেরা এটিকে ব্যাখ্যা করার জন্য কঠোর চেষ্টা করেছিল, আমি খুঁজে পেয়েছি সেরা উত্তর (এবং সবচেয়ে সহজ) উত্তরটি হ'ল বিবরণ পাইথন ডকুমেন্টেশনের ক্লাস পদ্ধতির ।

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

এই বিষয়ে আরও গভীর ও গভীরতার সাথে ডকুমেন্টেশনের মধ্যেও পাওয়া যাবে: স্ট্যান্ডার্ড টাইপ হায়ারার্কি ( ইনস্ট্যান্স পদ্ধতি পদ্ধতিতে স্ক্রোল করুন )


1

@classmethodবাইরের সংস্থান থেকে এই শ্রেণীর অবজেক্টগুলিকে সহজেই ইনস্ট্যান্ট করার জন্য দরকারী হতে পারে। নিম্নোক্ত বিবেচনা কর:

import settings

class SomeClass:
    @classmethod
    def from_settings(cls):
        return cls(settings=settings)

    def __init__(self, settings=None):
        if settings is not None:
            self.x = settings['x']
            self.y = settings['y']

তারপরে অন্য একটি ফাইলে:

from some_package import SomeClass

inst = SomeClass.from_settings()

Inst.x অ্যাক্সেস করা সেটিংস ['x'] এর সমান মান দেবে।


0

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

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

আপনি পুরো সেটটিতে কাজ করার জন্য সরঞ্জামগুলি সংজ্ঞায়িত করতে ক্লাসের পদ্ধতিগুলিও ব্যবহার করতে পারেন। উদাহরণস্বরূপ Student.all_of_em () সমস্ত পরিচিত শিক্ষার্থীদের ফিরিয়ে দিতে পারে। স্পষ্টতই যদি আপনার সেটগুলির সেটগুলিতে কেবল একটি সেটের চেয়ে বেশি কাঠামো থাকে তবে আপনি সেই কাঠামো সম্পর্কে জানার জন্য ক্লাসের পদ্ধতি সরবরাহ করতে পারেন। Students.all_of_em (গ্রেড = 'জুনিয়র')

এর মতো কৌশলগুলি শ্রেণীর ভেরিয়েবলের মূলযুক্ত ডেটা স্ট্রাকচারগুলিতে দৃষ্টান্তের সেটের সদস্যদের সঞ্চিত করে। আবর্জনা সংগ্রহ হতাশ এড়াতে আপনার যত্ন নেওয়া দরকার।

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