2015-07-29 5 views
1

Производный класс не имеет доступа к функциям элемента базового класса, если только я не ошибаюсь. Полученный класс также может получить доступ к атрибутам своего базового класса, предварительно назначив их следующим вызовам: BaseClass.base_attribute. Но я, кажется, не понимаю, как экземпляры производного класса могут использовать методы базового класса. Пример:Каков порядок пространств имен в наследовании?

class Visitor(): 
    """ Interface to Visitor 

    provide an interface to visitors that 
    perform an operation on a data collection """ 

    def visitProduce(): 
     pass 
    def visitMeat(): 
     pass 
    def visitBakedGoods(): 
     pass 
    def visitDairy(): 
     pass 
    def visitNonFood(): 
     pass 



class PriceVisitor(Visitor): 
    __cost = 0.0  # total cost of groceries 

    def __init__(self): 
     self.__cost = 0.0 
    def visitProduce(self, p): 
     self.__cost += p.price() 
    def visitMeat(self, m): 
     self.__cost += m.price() 
    def visitBakedGoods(self, b): 
     self.__cost += b.price() 
    def visitDairy(self, d): 
     self.__cost += d.price() 
    def visitNonFood(self, nf): 
     self.__cost += nf.price() 


class Groceries(): 
    shopping_cart = []  # list of grocery items 

    def Groceries(self): 
     self.shopping_cart = []  
    def addProduce(self, p): 
     pass 
    def addMeat(self, m, lb): 
     pass 
    def addBakedGoods(self, b): 
     pass 
    def addDairy(self, d): 
     pass 
    def addNonFood(self, nf): 
     pass 
    def accept(self, v): 
     pass 
    def getShoppingCart(self): 
     print(self.shopping_cart) 
    def calculateCost(self, v): 
     for item in self.shopping_cart: 
      item.accept(v) 
      item.details() 
      print('Total cost is: $', v.__cost) 



class Produce(Groceries): 
    def addProduce(self): 
     Groceries.shopping_cart.append(self) 

    def accept(self, v): 
     v.visitProduce(self) 

    def price(self): 
     return self.__price 

    def details(self): 
     print(self.__name, ' for: $', self.__price + '') 



class Apples(Produce): 
    __name = None 
    __price = 3.25 

    def __init__(self, name): 
     self.__name = name 

А вот тест Apple, продукты, бакалейные товары, и PriceVisitor классы

import VisitorPattern as vp 

def main(): 
    # Visitor object 
    my_visitor = vp.PriceVisitor() 

    # Grocery object stores objects in its shopping_cart attribute 
    my_groceries = vp.Groceries() 

    # Add items 
    red_apple = vp.Apples('red apple') 
    gold_apple = vp.Apples('gold apple') 
    red_apple.addProduce() 
    gold_apple.addProduce() 

    my_groceries.getShoppingCart() 

    my_groceries.calculateCost(my_visitor) 

if __name__ == '__main__': 
    main() 

Теперь, как я понимаю, что при построении экземпляра Apple, он имеет доступ к цене метода продукта(). Вызов этого метода с экземпляром класса Apple затем передаст свой собственный экземпляр вместо «я». Затем программа возвращает значение атрибута __price, принадлежащего экземпляру, вызывающему этот метод, в данном случае Apple. Тем не менее, я получаю эту ошибку:

C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4>python test. 
py 
[<VisitorPattern.Apples object at 0x026E0830>, <VisitorPattern.Apples object at 
0x026E0910>] 
Traceback (most recent call last): 
    File "test.py", line 23, in <module> 
    main() 
    File "test.py", line 20, in main 
    my_groceries.calculateCost(my_visitor) 
    File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi 
torPattern.py", line 60, in calculateCost 
    item.accept(v) 
    File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi 
torPattern.py", line 71, in accept 
    v.visitProduce(self) 
    File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi 
torPattern.py", line 28, in visitProduce 
    self.__cost += p.price() 
    File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi 
torPattern.py", line 74, in price 
    return self.__price 
AttributeError: 'Apples' object has no attribute '_Produce__price' 

Каким образом связывание и пространства имен действительно работают в наследовании? Я мог бы просто написать метод price() в каждом из производных классов Produce, но это победит точку наследования. Я думаю, что моя проблема также связана с изменением имени, но до сих пор не знаю, что произойдет, если я не сделаю свои атрибуты «частными». Уточнение было бы замечательным. Благодаря

Редактировать

Я объявил конструктор Бакалея неправильно:

# Wrong way 
def Groceries(self): 
    self.shopping_cart = [] 

# Should be 
def __init__(self): 
    self.__shopping_cart = [] 

Продукт полного времени работы и домашних заданий вечером

ответ

2

What is the order of namespaces in inheritance?

Python использует метод разрешения Order найти метод, связанный с этим экземпляром объекта.

Он также ссылается на название mangling, поэтому вы не можете найти метод, _Produce__price. Вы пытаетесь использовать .__price, но когда он унаследован, Python добавляет имя класса в начало имени. Не используйте два символа подчеркивания, измените два символа подчеркивания на один, и ваш код будет работать так, как вы ожидаете, и вы будете последовательно искать ._price, который не будет ссылаться на имя mangling.

Смотрите документацию для получения дополнительной информации:

https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

0

Не очень прямой ответ на все ваши вопросы, но я надеюсь, что следующий код проливает некоторый свет на то, как сделать наследование в Python.

class Produce(object): 

    def __init__(self, name=None, price=None): 
     self.__name = name 
     self.__price = price 

    def __str__(self): 
     return self.__name 

    @property 
    def bulk_price(self): 
     return self.__price * 100 

class Apple(Produce): 

    def __init__(self, name="Apple"): 
     self.__name = name 
     self.__price = 3.25 
     super(self.__class__, self).__init__(self.__name, self.__price) 

a = Apple("Gold Apple") 
print a 
print a.bulk_price 
# Gold Apple 
# 325.0 

Как вы можете видеть, я сделал name и price недоступную в обоих классах. Таким образом, я не могу просто вызвать их явно, т. Е. a.__price. Используя super, а также в дочернем классе, я могу избежать обращения к базовому классу далее , имея доступ к его методам.

+0

Я все еще должен программировать с C++: хорошо ли иметь атрибуты класса, или лучше оставить его для экземпляра, чтобы создать свой собственный атрибут? – Joe

+0

Я бы не назвал это хорошей практикой, но я не вижу причин, чтобы не иметь его в некоторых случаях. По общему признанию, я едва использовал атрибуты и методы класса в своем опыте работы с Python, поэтому я не думаю, что у меня есть возможность ответить на это за вас. – Manhattan

0

Я видел вашу ошибку, ваш родитель должен вызвать функцию ребенка, но вы не передали дочерний элемент родительскому, чтобы он получил ошибки.Теперь я даю пример:

class A: 
    def __init__(self, handler): 
     self.a = 5 
     self.real_handler = handler 

    def get(self): 
     print "value a = %d"%self.a 
     self.real_handler.put() 

class B(A): 
    def __init__(self): 
     A.__init__(self, self) ##transport B to A 
     self.b = 3 

    def get(self): 
     print "value b is %d"%self.b 
     A.get(self) 

    def put(self): 
     self.b = 6 
     print "value b change into %d"%self.b 

if __name__=="__main__": 
    b = B() 
    b.get() 

В родительском B, он будет вызывать фикцию у ребенка в put(). Я надеюсь это тебе поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^