2016-09-14 2 views
1

У меня есть следующий пример из питона page_object документы:Созданный родительский конструктор по умолчанию?

from page_objects import PageObject, PageElement 
from selenium import webdriver 

class LoginPage(PageObject): 
     username = PageElement(id_='username') 
     password = PageElement(name='password') 
     login = PageElement(css='input[type="submit"]') 

driver = webdriver.PhantomJS() 
driver.get("http://example.com") 
page = LoginPage(driver) 
page.username = 'secret' 
page.password = 'squirrel' 
assert page.username.text == 'secret' 
page.login.click() 

Что меня беспокоит то, что мы создаем LoginPage с обеспечением driver на это конструктор, но мы не определить метод __init__ в LoginPage классе.

Означает ли это, что конструктор родительского класса PageObject вызывается с параметром driver? Я думал, что python не подразумевает вызов конструкторов родителя?

+2

Если вы не определите '__init__' метод, используется родительская реализация, как правило. – keksnicoh

+1

, если дочерний конструктор не существует, родительский конструктор будет автоматически запускаться. –

ответ

1

Метод __init__ - это всего лишь метод, и как таковой python выполняет такой же поиск для него, как и другие методы. Если класс B не определяет метод/атрибут x, тогда python ищет его базовый класс A и так далее, пока он не найдет атрибут/метод или не сработает.

Простой пример:

>>> class A: 
...  def method(self): 
...   print('A') 
... 
>>> class B(A): pass 
... 
>>> class C(B): 
...  def method(self): 
...   print('C') 
... 
>>> a = A() 
>>> b = B() 
>>> c = C() 
>>> a.method() 
A 
>>> b.method() # doesn't find B.method, and so uses A.method 
A 
>>> c.method() 
C 

То же самое с __init__: поскольку LoginPage не определяет __init__ питон просматривает PageObject класс и находит свое определение там.

Что означает, когда мы говорим, что «питон не неявно называют родительский классом конструктора» является то, что если вы определяете __init__ метод интерпретатор просто называть этот метод и не вызова всех родительского класса __init__ лет , и поэтому, если вы хотите вызвать конструктор родительского класса, вы должны сделать это явно.

Обратите внимание на различие между этими классами:

>>> class A: 
...  def __init__(self): 
...   print('A') 
... 
>>> class B(A): 
...  pass 
... 
>>> class B2(A): 
...  def __init__(self): 
...   print('B') 
... 
>>> class B3(A): 
...  def __init__(self): 
...   print('B3') 
...   super().__init__() 
... 
>>> A() 
A 
<__main__.A object at 0x7f5193267eb8> 
>>> B() # B.__init__ does not exists, uses A.__init__ 
A 
<__main__.B object at 0x7f5193267ef0> 
>>> B2() # B2.__init__ exists, no call to A.__init__ 
B 
<__main__.B2 object at 0x7f5193267eb8> 
>>> B3() # B3.__init__exists, and calls to A.__init__ too 
B3 
A 
<__main__.B3 object at 0x7f5193267ef0> 
+0

спасибо за хорошее объяснение :) – CuriousGuy

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