Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 27, 2011 00:05:56

klrk
От:
Зарегистрирован: 2011-01-26
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование в Python

Добрый вечер!
Недавно начал разбираться с ООП в 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’. Подскажите, пожалуйста, что не так? И, возможно, будут какие-то рекомендации к архитектуре класса?

Заранее большое спасибо!



Отредактировано (Янв. 27, 2011 12:22:59)

Офлайн

#2 Янв. 27, 2011 02:01:56

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Наследование в Python

Вызывайте в конструкторе своего родителя.
И не называйте методы __method, не нужно..



Офлайн

#3 Янв. 27, 2011 02:03:17

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Наследование в Python

Ну это и не удивительно :)
Ваш конструктор класса Auth нужно дополнить одной строкой:

super(Auth, self).__init__()
таким образом вы избавитесь от указанной ошибки (правда, при этом попадете в бесконечный цикл :()



Офлайн

#4 Янв. 27, 2011 09:51:24

klrk
От:
Зарегистрирован: 2011-01-26
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование в Python

Андрей Светлов, pyuser,
Большое спасибо за ответы!

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

pyuser
таким образом вы избавитесь от указанной ошибки (правда, при этом попадете в бесконечный цикл sad)
А какие последствия этого?



Офлайн

#5 Янв. 27, 2011 10:46:37

pyuser
От:
Зарегистрирован: 2007-05-13
Сообщения: 658
Репутация: +  36  -
Профиль   Отправить e-mail  

Наследование в Python

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



Офлайн

#6 Янв. 27, 2011 12:22:42

klrk
От:
Зарегистрирован: 2011-01-26
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование в Python

pyuser, понятно, большое спасибо!

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

А что бы Вы посоветовали в этой ситуации?



Офлайн

#7 Янв. 27, 2011 12:51:17

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Наследование в Python

Что такое Bot и что такое Auth и почему один является наследником другого?

Bot.Auth.method1
В вашем примере Auth не наследник Bot, а его свойство.



Офлайн

#8 Янв. 27, 2011 13:36:18

klrk
От:
Зарегистрирован: 2011-01-26
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование в Python

Soteric, спасибо, уже понял эту ошибку. А есть ли какие-то способы доступа к атрибуту базового класса (в данном случае Bot.opener) из методов свойства (Bot.Auth)?



Офлайн

#9 Янв. 27, 2011 13:57:12

Soteric
От:
Зарегистрирован: 2010-09-19
Сообщения: 352
Репутация: +  20  -
Профиль   Отправить e-mail  

Наследование в Python

Не понял вопроса. Если некий экземпляр Auth является свойством Bot, то чтобы получить доступ к методам Bot, ему также необходимо иметь на него ссылку в виде свойства/поля (и здесь не играет роли кто чьим родителем/наследником является). Если Auth является наследником Bot, то он может обращаться ко всем открытым методам своего родителя как к своим (при этом Bot.Auth как я уже сказал не является отношением родитель-наследник и Auth здесь никак не может управлять Bot - они здесь два разных независимых друг от друга объекта). Лучше объясните что вы пытаетесь получить, какую смысловую нагрузку несут ваши классы Bot, Auth и Info, а вам объяснят как правильно организовать между ними связь (в виде наследования или нет). Потому что сейчас особой связи между ними я не вижу.



Офлайн

#10 Янв. 27, 2011 14:31:54

klrk
От:
Зарегистрирован: 2011-01-26
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Наследование в Python

Soteric,
Есть сайт, на котором нужно программно имитировать поведение человека (Bot). Бот должен проходить авторизацию различными методами (саб-класс Auth)/менять различную информацию (Info)/и т.д. Можно, конечно, реализовать все это в Bot, добавляя к имени каждого метода тип его применения (вроде Bot.AuthByMail()), но т.к. для каждого типа методов может быть достаточно много, мне захотелось “выделить” из в отдельные классы (Bot.Auth.byMail()).

Проблема заключается в том, что все вспомогательные классы для соединения с сайтом должны использовать opener, описанный в Bot, и я не нашел способа, как сделать это без явной передачи этого атрибута в конструктор каждого из подклассов.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version