পাইথনে ইনস্ট্যান্স ভেরিয়েবল বনাম ক্লাস ভেরিয়েবল


120

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

শ্রেণি ভেরিয়েবল:

class MyController(Controller):

  path = "something/"
  children = [AController, BController]

  def action(self, request):
    pass

উদাহরণস্বরূপ ভেরিয়েবল:

class MyController(Controller):

  def __init__(self):
    self.path = "something/"
    self.children = [AController, BController]

  def action(self, request):
    pass

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

উত্তর:


158

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


7
বর্গ প্যাটার্নের কথা কখনও শুনেনি? কেবলমাত্র একটি উদাহরণ থাকা প্রথম স্থানে থাকার ভুল উপায় ছিল।
ডেভিন জিনপিয়ের

434
@ ডেভিন, হ্যাঁ, আমি বর্গের প্যাটার্নের কথা শুনেছি, যেহেতু আমিই এটির পরিচয় দিয়েছি (2001 সালে, সিএফআর কোড.এ্যাকটিভেটসেট / রিসিপস /; ;-)। তবে কোনও সমস্যা নেই, সাধারণ ক্ষেত্রে, কেবল কোনও প্রয়োগ নেই এমন একক দৃষ্টান্ত রয়েছে।
অ্যালেক্স মার্টেলি

2
@ ব্যবহারকারী 1767754, এগুলি দিয়ে নিজেকে তৈরি করা সহজ python -mtimeit- তবে অজগর 3.4 এ সবেমাত্র সম্পন্ন করে আমি নোট করেছি যে একটি intক্লাস ভেরিয়েবল অ্যাক্সেস করা আমার পুরানো ওয়ার্কস্টেশনে উদাহরণ পরিবর্তনশীল হিসাবে প্রায় 5 থেকে 11 ন্যানোসেকেন্ড দ্রুত - এটি নিশ্চিত নয় কোডপথ এটি তাই করে তোলে।
অ্যালেক্স মার্তেলি

45

মাইক এবং অ্যালেক্সের পরামর্শকে আরও প্রতিধ্বনি করা এবং আমার নিজের রঙ যুক্ত করা ...

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

অ্যালেক্স তার জবাবে উল্লেখ করেছে যে অল্প অল্প মাত্রা দেখার কারণে অ্যাক্সেস (সামান্য) দ্রুত হবে ... আমাকে কী আরও কীভাবে এটি এখনও কাজ করে না তা জানেন না তাদের জন্য আরও স্পষ্ট করে বলি। এটি ভেরিয়েবল অ্যাক্সেসের সাথে খুব মিল - এর অনুসন্ধান ক্রমটি যা:

  1. অঁচলবাসী
  2. nonlocals
  3. globals
  4. বিল্ট-ইন

বৈশিষ্ট্য অ্যাক্সেসের জন্য, অর্ডারটি হ'ল:

  1. দৃষ্টান্ত
  2. শ্রেণী
  3. এমআরও দ্বারা নির্ধারিত বেস ক্লাস (পদ্ধতি সমাধানের আদেশ)

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

আপনার উপরের উদাহরণে, আসুন আমরা এই pathবৈশিষ্ট্যটি সন্ধান করছি say যখন এটি " self.path" এর মতো কোনও রেফারেন্সের মুখোমুখি হয় , পাইথন ম্যাচের জন্য প্রথমে উদাহরণের বৈশিষ্ট্যগুলি দেখবে। যখন এটি ব্যর্থ হয়, এটি ক্লাসটি পরীক্ষা করে যেখান থেকে বস্তুটি ইনস্ট্যান্ট করা হয়েছিল। শেষ পর্যন্ত, এটি বেস ক্লাসগুলি অনুসন্ধান করবে। অ্যালেক্স যেমন বলেছিল, আপনার বৈশিষ্ট্যটি যদি এই দৃষ্টিতে খুঁজে পাওয়া যায়, তবে এটি অন্য কোথাও দেখার দরকার নেই, তাই আপনার সময় সাশ্রয়ের সামান্য পরিমাণ।

তবে, আপনি যদি শ্রেণীর বৈশিষ্ট্যগুলিতে জোর দিয়ে থাকেন তবে আপনার সেই অতিরিক্ত অনুসন্ধান দরকার। অথবা , আপনার অন্য বিকল্প বর্গ পরিবর্তে উদাহরণস্বরূপ, যেমন মাধ্যমে বস্তুর উল্লেখ করতে হয়, MyController.pathপরিবর্তে self.path। এটি একটি প্রত্যক্ষ অনুসন্ধান যা স্থগিত অনুসন্ধানের আশেপাশে পাওয়া যাবে, তবে নীচে অ্যালেক্সের হিসাবে উল্লেখ করা হয়েছে, এটি একটি বৈশ্বিক পরিবর্তনশীল, সুতরাং আপনি যে বিটটি হারিয়েছেন আপনি ভেবেছিলেন যে আপনি সংরক্ষণ করতে যাচ্ছেন (যদি না আপনি [বিশ্বব্যাপী] শ্রেণীর নামের একটি স্থানীয় রেফারেন্স না তৈরি করেন) )।

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


@wescpy কিন্তু MyController, globals মধ্যে তাকিয়ে তাই মোট খরচ বেশী হয় self.pathযেখানে pathএকটি দৃষ্টান্ত পরিবর্তনশীল (যেহেতু selfহয় স্থানীয় পদ্ধতি == অতিদ্রুত অনুসন্ধান করতে)।
অ্যালেক্স মার্টেলি

আহ, সত্য ভালো বল ধরা. আমি অনুমান করি যে একমাত্র কাজটিই স্থানীয় রেফারেন্স তৈরি করা ... এই মুহুর্তে, এটি সত্যিকার অর্থে উপযুক্ত নয়।
wescpy

24

সন্দেহ হলে, আপনি সম্ভবত একটি উদাহরণ বৈশিষ্ট্য চান।

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


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

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

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

গুগলের পাইথন স্টাইল গাইডের একটি নতুন লিঙ্ক এখানে । এখন কেবল সেখানে লিখিত আছে: avoid global variablesএবং তাদের সংজ্ঞাটি হ'ল, বৈশ্বিক চলকগুলিও এমন ভেরিয়েবল যা শ্রেণি বৈশিষ্ট্য হিসাবে ঘোষণা করা হয়। তবে পাইথনের নিজস্ব স্টাইল গাইড ( পিইপি -8 ) এই ধরণের প্রশ্নগুলির জন্য প্রথম স্থান হওয়া উচিত। তারপরে আপনার নিজের মন পছন্দনীয় হাতিয়ার হওয়া উচিত (অবশ্যই আপনি গুগল থেকে ধারণাও পেতে পারেন, উদাহরণস্বরূপ)।
কলিডিয়ার

4

পাইথনে ক্লাস ভেরিয়েবল অ্যাক্সেস করার পারফরম্যান্সে একই প্রশ্ন - এখানে কোডটি @ অ্যাডওয়ার্ড লোপার থেকে অভিযোজিত

স্থানীয় ভেরিয়েবলগুলি অ্যাক্সেসের পক্ষে দ্রুততম, মডিউল ভেরিয়েবলগুলির সাথে অনেকটা বাঁধা, ক্লাস ভেরিয়েবলগুলির পরে, ইনস্ট্যান্স ভেরিয়েবলগুলির পরে।

এখানে 4 টি স্কোপ রয়েছে যা থেকে আপনি ভেরিয়েবলগুলি অ্যাক্সেস করতে পারবেন:

  1. ইনস্ট্যান্স ভেরিয়েবলস (স্ব.বর্ণনাম)
  2. ক্লাস ভেরিয়েবলস (Classname.varname)
  3. মডিউল ভেরিয়েবল (VARNAME)
  4. স্থানীয় চলক (নাম)

পরীক্ষা:

import timeit

setup='''
XGLOBAL= 5
class A:
    xclass = 5
    def __init__(self):
        self.xinstance = 5
    def f1(self):
        xlocal = 5
        x = self.xinstance
    def f2(self):
        xlocal = 5
        x = A.xclass
    def f3(self):
        xlocal = 5
        x = XGLOBAL
    def f4(self):
        xlocal = 5
        x = xlocal
a = A()
'''
print('access via instance variable: %.3f' % timeit.timeit('a.f1()', setup=setup, number=300000000) )
print('access via class variable: %.3f' % timeit.timeit('a.f2()', setup=setup, number=300000000) )
print('access via module variable: %.3f' % timeit.timeit('a.f3()', setup=setup, number=300000000) )
print('access via local variable: %.3f' % timeit.timeit('a.f4()', setup=setup, number=300000000) )

ফলাফল:

access via instance variable: 93.456
access via class variable: 82.169
access via module variable: 72.634
access via local variable: 72.199
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.