Присоединение к Python: почему это string.join (список) вместо list.join (строка)?

Ответ Антона работал, и на какое-то время был достойный ответ, но, к сожалению, он стал недостижимым. Итак, взяв сигнал из diff , прикрепленный к билету django # 9230 , я просто обезглавил django.forms.forms.BoundField

from django import forms

def MonkeyPatchDjangoFormsBoundField():
    def prepare_widget_render(self, widget=None, attrs=None, only_initial=False):
        """
        Prepare the data needed for the widget rendering.
        """
        if not widget:
            widget = self.field.widget

        attrs = attrs or {}
        auto_id = self.auto_id
        if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
            if not only_initial:
                attrs['id'] = auto_id
            else:
                attrs['id'] = self.html_initial_id

        if not only_initial:
            name = self.html_name
        else:
            name = self.html_initial_name

        return widget, name, attrs

    def as_widget(self, widget=None, attrs=None, only_initial=False):
        """
        Renders the field by rendering the passed widget, adding any HTML
        attributes passed as attrs.  If no widget is specified, then the
        field's default widget will be used.
        """
        widget, name, attrs = self.prepare_widget_render(widget, attrs, only_initial)
        return widget.render(name, self.value(), attrs=attrs)

    def __iter__(self):
        """
        Check if current widget has a renderer and iterate renderer.
        """
        widget, name, attrs = self.prepare_widget_render()
        if not hasattr(widget, 'get_renderer'):
            raise Exception, "Can not iterate over widget '%s'" % widget.__class__.__name__
        renderer = widget.get_renderer(name, self.value(), attrs=attrs)
        for entry in renderer:
            yield entry

    def __getitem__(self,idx):
        """
        Tries to use current widget's renderer, and then check attribute.
        """
        widget, name, attrs = self.prepare_widget_render()
        try:
            renderer = widget.get_renderer(name, self.value(), attrs=attrs)
            return renderer[idx]
        except Exception:
            return getattr(self,idx)

    forms.forms.BoundField.prepare_widget_render = prepare_widget_render
    forms.forms.BoundField.as_widget = as_widget
    forms.forms.BoundField.__iter__ = __iter__
    forms.forms.BoundField.__getitem__ = __getitem__

Это позволило мне иметь доступ к радиовводам напрямую, используя {{ form.field.0.tag }} или через итерацию - {% for radio in form.field %} {{ radio.tag }} {% endfor %}. Намного легче позаботиться!

1606
задан rrao 21 December 2016 в 11:29
поделиться

6 ответов

Это - потому что к любому повторяемому можно присоединиться, не только перечисляет, но и результатом и "столяром" всегда являются строки.

, Например:

import urllib2
print('\n############\n'.join(
    urllib2.urlopen('http://data.stackexchange.com/users/7095')))
1197
ответ дан Boris 23 September 2019 в 15:59
поделиться

Поскольку join() метод находится в строковом классе вместо класса списка?

я соглашаюсь, что это выглядит забавным.

См. http://www.faqs.org/docs/diveintopython/odbchelper_join.html :

Исторический очерк. , Когда я сначала изучил Python, я ожидал, что соединение будет методом списка, который возьмет разделитель в качестве аргумента. Много людей чувствует то же самое, и there’s история метода соединения. До Python 1.6 строковые didn’t имеют все эти полезные методы. Был отдельный строковый модуль, который содержал все строковые функции; каждая функция взяла строку в качестве своего первого аргумента. Функции считали достаточно важными для помещения на сами строки, которые имели смысл для функций как более низкий, верхнее, и разделяли. Но многие жесткие Python программисты возразили против нового метода соединения, утверждая, что это должен быть метод списка вместо этого, или что это, перемещение shouldn’t вообще, но просто остается частью старого строкового модуля (который все еще имеет много полезного материала в нем). Я использую новый метод соединения исключительно, но Вы будете видеть код, написанный так или иначе, и если он действительно беспокоит Вас, можно использовать старую функцию string.join вместо этого.

---Mark Pilgrim, Погружение в Python

245
ответ дан Brian Burns 23 September 2019 в 15:59
поделиться

Я соглашаюсь, что это парадоксально сначала, но существует серьезное основание. Соединение не может быть методом списка потому что:

  • это должно работать на другой iterables также (кортежи, генераторы, и т.д.)
  • это должно иметь другое поведение между различными типами строк.

существует на самом деле два метода соединения (Python 3.0):

>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>

, Если бы соединение было методом списка, то оно должно было бы осмотреть свои аргументы для решения который из них звонить. И Вы не можете присоединиться к байту и ул. вместе, таким образом, способ, которым у них есть он теперь, имеет смысл.

64
ответ дан Kiv 23 September 2019 в 15:59
поделиться

Думайте о нем как о естественной ортогональной операции для разделения.

я понимаю, почему это применимо к чему-либо повторяемому и так не может легко быть реализовано всего в списке.

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

24
ответ дан Andy Dent 23 September 2019 в 15:59
поделиться

Прежде всего, потому что результатом someString.join() является строка.

последовательность (список или кортеж или безотносительно) не появляется в результате, просто строка. Поскольку результатом является строка, он имеет смысл как метод строки.

13
ответ дан S.Lott 23 September 2019 в 15:59
поделиться

Переменные my_list и "-" являются оба объектами. А именно, они - экземпляры классов list и str, соответственно. Эти join функция принадлежит классу str. Поэтому синтаксис "-".join(my_list) используется, потому что объект "-" берет my_list в качестве входа.

0
ответ дан 22 November 2019 в 20:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: