2011-06-01 19 views
9

एक घंटे पहले तक, मुझे विश्वास था कि पाइथन Foo().bar()Foo.bar (Foo()) के लिए एक छोटा सा हाथ से अधिक कुछ नहीं था जो उदाहरण को पहले पैरामीटर के रूप में पास करता है। इस उदाहरण में अंतिम दो पंक्तियों करना (जाहिरा तौर पर) एक ही बात:पायथन विधि लुकअप, स्थैतिक बनाम उदाहरण

class Foo (object): 
    def bar (self): print "baz" 

qux = Foo() 
qux.bar() 
Foo.bar (qux) 

लेकिन अब मैं एक वर्ग पशु एक स्थिर विधि से भरें() कि इंसान को मालूम सभी जानवरों की सूची लौटाता है कि है। इसके अलावा पशु के प्रत्येक उदाहरण में एक विधि पॉप्युलेट() है जो उदाहरण के गुणों को यादृच्छिक मानों से भरती है।

#! /usr/bin/env python 
# -*- coding: utf-8 -*- 

import random 

animals = [ ("Bella", "cow"), ("Spike", "dog"), ("José", "iguana"), ("Tux", "penguin") ] 

class Animal (object): 
    @staticmethod 
    def populate (*args): return map (lambda x: Animal (*x), animals) 

    def __init__ (self, name = None, species = None): 
     def bar(): self.name, self.species = random.choice (animals) 
     self.name = name 
     self.species = species 
     self.populate = bar 

    def __repr__ (self): return "%s of species %s" % (self.name, self.species) 

print Animal.populate() 
print Animal ("Pinky", "mouse") 
qux = Animal() 
qux.populate() 
print qux 

कोड ठीक काम करता है, लेकिन क्या मुझे संदिग्ध बना तथ्य print Animal.populate (qux) कहा जाता है कि स्थिर रूप से भरें विधि (और इसलिए एक सूची लौट आए और गरीब qux पॉप्युलेट नहीं था) था। तो स्पष्ट रूप से मेरा दृढ़ विश्वास कि Foo().bar()Foo.bar (Foo()) के लिए एक छोटा सा हाथ से कुछ भी गलत नहीं था।

यह मेरे लिए विभिन्न सवाल उठे:

  1. क्या होता है जब मैं Foo().bar() कहते हैं?
  2. क्या होता है जब मैं Foo.bar (Foo()) पर कॉल करता हूं?
  3. क्या दोनों के बीच कोई आंतरिक अंतर है?
  4. क्या मुझे अजगर की कुछ मौलिक अवधारणा याद आ रही है?
  5. यदि आपको ऐसी कक्षा लिखनी पड़ेगी जिसकी स्थिर आबादी विधि इस वर्ग के उदाहरण पर आबादी वाले विधि से कुछ और करती है, तो कौन सा रास्ता होगा?

(हाँ, यह एक ही नाम होना चाहिए।)

+0

एक और दिलचस्प शीर्षक "पायथन विधि लुकअप, स्थैतिक बनाम उदाहरण" होगा। आपको उस शब्दावली का उपयोग करके अधिक उत्तर मिल सकते हैं, यह थोड़ा और तकनीकी और आकर्षक है। – slezica

+0

@ सैंटियागो इनपुट के लिए धन्यवाद। मैंने शीर्षक बदल दिया। – Hyperboreus

+2

'()' के आसपास की सभी अतिरिक्त रिक्त स्थान मेरी आंखों को चोट पहुंचाती हैं –

उत्तर

2

में पहला कदम बार(), Foo.bar (फू()) और Foo.bar() (लंघन है। कल साइन अप किया गया है और अभी तक टिप्पणियां पोस्ट नहीं कर सकता है) - यह पाइथन (< 3.0) की 'बाध्य' और 'अनबाउंड' विधियों की अवधारणा के कारण है - इसे सख्ती से इसकी आवश्यकता है, @staticmethod या @classmethod को छोड़कर, विधि कॉल के पास उनके साथ जुड़े एक उदाहरण। आपको याद रखने के लिए बस कुछ समझाने का कोई आसान तरीका नहीं है। शुक्र है, यह पाइथन 3 में बदल गया है - 'बाध्य' और 'अनबाउंड' विधियों की अवधारणा के रूप में अलग चीजें चली गई हैं, और Foo.bar() आपके उदाहरण के लिए ठीक काम करता है।

+0

ग्रेट। इससे बहुत मदद मिली। – Hyperboreus

+0

मैं सिर्फ python2.7 से python3.2 तक चले गए और अब मुझे पहले की तुलना में कम "आश्चर्य" का अनुभव होता है। – Hyperboreus

2

स्टेटिक तरीकों और वर्ग तरीकों special descriptors हैं। चूंकि वर्णनकर्ता के __get__() विधि के तर्कों में कक्षा और किसी भी प्रासंगिक उदाहरण दोनों शामिल हैं, वे किसी भी तरह से विधि के तर्कों के साथ स्क्रू कर सकते हैं।

+0

धन्यवाद। मैं लिंक पढ़ूंगा और शायद अधिक प्रश्नों के साथ वापस आऊंगा। – Hyperboreus

0

qnx.populate()populate के लिए उदाहरण qnx पर पहली बार दिखता है। यदि ऐसा नहीं है तो __mro__ तब तक पालन किया जाता है जब तक populate नामक कुछ नहीं मिलता है।

Animals.populate(qnx) क्योंकि मैं एक जवाब के रूप फू() के बीच अंतर पर ऊपर देखने

+0

बहुत बहुत धन्यवाद। मुझे इसे पचाने के लिए कुछ समय चाहिए। – Hyperboreus

+0

क्या पाइथन में एमआरओ के साथ पता लगाने का कोई तरीका है? – Hyperboreus

+0

@ हाइपरबोरियस, कक्षा में '__mro__' विशेषता –

संबंधित मुद्दे