Управление атрибутами из производного класса namedtuple()

У меня есть класс под названием EasyUrl() что происходит от urlparse.Parseresult(), ParseResult() создается при вызове urlparse.urlparse(url)У меня есть статический метод внутри EasyUrl() который изменяет тип класса экземпляра ParseResult() возражать в EasyUrl() объект. Я завернуть urlparse.urlparse() функция и преобразование типа класса в функцию parse_url(),

Причиной такой функции является моя попытка обойти отдельную проблему, на которую я не требую ответа, но хотел бы, чтобы я получил TypeError когда __new__ вызывается во время процесса создания экземпляра, который дает мне знать, что у меня неверное количество аргументов.

Ошибка при создании экземпляра EasyUrl() непосредственно

# snippet 
url = 'stackru.com'
url = EasyUrl(url)
# snippet end

Output:
TypeError: __new__() takes exactly 7 arguments (2 given)

ParseResult() класс наследует от namedtuple(),

Выдержка из библиотеки urlparse

class ParseResult(namedtuple('ParseResult', 'scheme netloc path params query fragment'), ResultMixin):

    __slots__ = ()

    def geturl(self):
        return urlunparse(self)

Теперь, когда я описал немного функциональности кода, вот проблема. Я не могу получить доступ к атрибутам именованного кортежа (ParseResult). Я пытаюсь реализовать схему по умолчанию для ParseResult() если это отсутствует.

Но я не могу получить доступ к атрибутам в определении класса.

import urlparse


def parse_url(url):
    """ Return a parsed EasyUrl() object"""
    parse_result = urlparse.urlparse(url)
    return EasyUrl.EvolveParseResult(parse_result)


class EasyUrl(urlparse.ParseResult):

    @staticmethod
    def EvolveParseResult(parse_result):
        """ Change the type of class into a EasyUrl() Object."""
        parse_result.__class__ = EasyUrl
        easy_url = parse_result # For readabilty
        easy_url.init()
        return easy_url

    def __init__(self, url):
        self = parse_url(url) # doesn't work

    def init(self):
        self.url = self.geturl()
        #self.set_scheme_if_non() # Uncomment when no error is raised

    def set_scheme_if_non(self, scheme='http'):
        if not self.scheme:
            self.scheme = scheme
            self.url = self.geturl() # Rebuild our url with the new scheme



# Passes the set_scheme_if_non trigger
#url = 'https://stackru.com'
# Fails if statment, then attempts to set the variable,
# but error is raised: AttributeError: can't set attribute
url = 'stackru.com'

# Will give the error: TypeError: __new__() takes exactly 7 arguments (2 given)
#url = EasyUrl(url)

# works fine, I don't know why. Except that I can't access
# the tuples attributes in the class definition
url = parse_url(url) 

print url.scheme # Works fine

url.set_scheme_if_non() # Raises an error

Выход

File "/home/crispycret/easyurl.py", line 50, in <module>
  url.set_scheme_if_non() # Raises an error
File "/home/crispycret/easyurl.py", line 29, in set_scheme_if_non
  self.scheme = scheme

AttributeError: can't set attribute

1 ответ

Решение

Почему бы не создать новый класс с нуля и перенести все атрибуты из ParseResult над?

import urlparse

class EasyURL(object):
    def __init__(self, parse_result):
        self.scheme = parse_result.scheme
        self.netloc = parse_result.netloc
        self.path = parse_result.path
        self.params = parse_result.params
        self.query = parse_result.query
        self.fragment = parse_result.fragment

    @classmethod
    def from_url(cls, url):
        return cls(urlparse.urlparse(url))

if __name__ == '__main__':
    url = 'http://foo.bar.com:8888/path/to/script.php?a=1&b=2'

    # Call from_url class method, which is very convenient
    easy_url = EasyURL.from_url(url)

    # Or, do it yourself
    easy_url = EasyURL(urlparse.urlparse(url))

Теперь вы можете добавить любой дополнительный метод к этому классу по желанию.

Обновить

  • namedtuple это функция, которая создает новый тип на лету Кстати, наш EasyURL объект не будет действовать как кортеж, если мы не добавим код для __getitem__()
  • ParseResult не позволяет вам изменять свои атрибуты, такие как schemeпоэтому нет оснований наследовать от него.
Другие вопросы по тегам