Найти - Пользователи
Полная версия: Наследование в Python
Начало » Python для новичков » Наследование в Python
1 2
klrk
Добрый вечер!
Недавно начал разбираться с ООП в Python, и при написании небольшого скрипта столкнулся со следующей проблемой:

class Bot(object):
def __init__(self):
self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))

# subclasses
self.Auth = Auth()
self.Info = Info()
# more subclasses

def __setProxy(self, proxy):
self.opener.add_handler(urllib2.ProxyHandler({'http' : proxy}))
pass

class Auth(Bot):
def __init__(self):
self.login = None
self.passw = None
self.sid = None

def LoginAuth(self, login, pwd, proxy={}):
if proxy:
self.__setProxy(proxy)
self.login, self.passw = login, pwd

data = urllib.urlencode(
{
'login' : self.email,
'password' : self.passw
}
)
html = self.opener.open("http://...", data).read()

if (html.find("authorized") != -1):
return True

return False

def CookieAuth(self, cookie, proxy={}):
if proxy:
self.__setProxy(proxy)
self.sid = cookie

self.opener.addheaders = [
('Cookie', 'sid='+self.sid)
]

html = self.opener.open("http://...").read()
if (html.find("authorized") != -1):
return True

return False

class Info(Bot):
def __init__(self):
pass

# # # # # # # #
X = Bot()
X.Auth.CookieAuth("cookie")
Вылетает в строке self.opener.addheaders = с AttributeError: ‘Auth’ object has no attribute ‘opener’. Подскажите, пожалуйста, что не так? И, возможно, будут какие-то рекомендации к архитектуре класса?

Заранее большое спасибо!
Андрей Светлов
Вызывайте в конструкторе своего родителя.
И не называйте методы __method, не нужно..
pyuser
Ну это и не удивительно :)
Ваш конструктор класса Auth нужно дополнить одной строкой:
super(Auth, self).__init__()
таким образом вы избавитесь от указанной ошибки (правда, при этом попадете в бесконечный цикл :()
klrk
Андрей Светлов, pyuser,
Большое спасибо за ответы!

Андрей Светлов
И не называйте методы __method, не нужно..
А почему? Читал, что по-настоящему приватных методов в Питоне нету, и к __method всё-равно можно будет обратиться через Class._Class__method, но почему-то решил использовать :) Причина неиспользования в этом, или есть что-то ещё?

pyuser
таким образом вы избавитесь от указанной ошибки (правда, при этом попадете в бесконечный цикл sad)
А какие последствия этого?
pyuser
klrk
А какие последствия этого?
Не попробуете - не узнаете :D
Посмотрите на свой код, у Вас при создании объекта класса Bot создается объект класса Auth, при создании которого вызывается конструктор класса Bot, который, в свою очередь, снова попытается создать объект класса Auth, … и так до бесконечности :)
klrk
pyuser, понятно, большое спасибо!

Мне бы не хотелось выносить всю реализацию в Bot, гораздо нагляднее, как мне кажется, с текущей структурой - Bot.Auth.method1 и т.п.. Первое, что пришло на ум - в каждом саб-классе хранить копию opener из Bot, но почему-то не нравится мне такой метод :)

А что бы Вы посоветовали в этой ситуации?
Soteric
Что такое Bot и что такое Auth и почему один является наследником другого?
Bot.Auth.method1
В вашем примере Auth не наследник Bot, а его свойство.
klrk
Soteric, спасибо, уже понял эту ошибку. А есть ли какие-то способы доступа к атрибуту базового класса (в данном случае Bot.opener) из методов свойства (Bot.Auth)?
Soteric
Не понял вопроса. Если некий экземпляр Auth является свойством Bot, то чтобы получить доступ к методам Bot, ему также необходимо иметь на него ссылку в виде свойства/поля (и здесь не играет роли кто чьим родителем/наследником является). Если Auth является наследником Bot, то он может обращаться ко всем открытым методам своего родителя как к своим (при этом Bot.Auth как я уже сказал не является отношением родитель-наследник и Auth здесь никак не может управлять Bot - они здесь два разных независимых друг от друга объекта). Лучше объясните что вы пытаетесь получить, какую смысловую нагрузку несут ваши классы Bot, Auth и Info, а вам объяснят как правильно организовать между ними связь (в виде наследования или нет). Потому что сейчас особой связи между ними я не вижу.
klrk
Soteric,
Есть сайт, на котором нужно программно имитировать поведение человека (Bot). Бот должен проходить авторизацию различными методами (саб-класс Auth)/менять различную информацию (Info)/и т.д. Можно, конечно, реализовать все это в Bot, добавляя к имени каждого метода тип его применения (вроде Bot.AuthByMail()), но т.к. для каждого типа методов может быть достаточно много, мне захотелось “выделить” из в отдельные классы (Bot.Auth.byMail()).

Проблема заключается в том, что все вспомогательные классы для соединения с сайтом должны использовать opener, описанный в Bot, и я не нашел способа, как сделать это без явной передачи этого атрибута в конструктор каждого из подклассов.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB