Объект, который реализует & ldquo; протокол итератора & rdquo; с помощью отдельных атрибутов не распознается как итеративный [дубликат]

Вы можете использовать массив в строке для создания этого df не на выходе

newdf = df.groupBy('aaa')
  .agg(F.collect_list('bbb').("string").alias('ccc'))

outputdf = newdf.select(
  F.concat_ws(', ' , newdf.aaa, F.format_string('xxxxx(%s)', newdf.ccc)))
14
задан juliomalegria 30 April 2012 в 00:50
поделиться

4 ответа

Python не вызывает специальные методы, те, у которых имя окружено __ экземпляром, но только на классе, по-видимому, для повышения производительности. Таким образом, нет возможности переопределить __repr__() непосредственно на экземпляре и заставить его работать. Вместо этого вам нужно сделать что-то вроде этого:

class A(object):
    def __repr__(self):
        return self._repr()
    def _repr(self):
        return object.__repr__(self)

Теперь вы можете переопределить __repr__() в экземпляре, заменив _repr().

16
ответ дан I159 26 August 2018 в 13:38
поделиться

Как объяснено в Special Method Lookup :

Для пользовательских классов неявные вызовы специальных методов гарантируют, что они будут работать корректно, если они определены для типа объекта, а не в словаре экземпляра объекта ... Помимо обхода любых атрибутов экземпляра в интересах корректности, неявный поиск специальных методов обычно также обходит метод __getattribute__() даже метакласса объекта

(часть Я вырвался из объяснения причин этого, если вы заинтересованы в этом.)

Python не документирует точно, когда реализация должна или не должна искать метод по типу; все эти документы, по сути, являются реалиями, которые могут или не могут смотреть на экземпляр для специальных поисков методов, поэтому вы не должны рассчитывать ни на.

Как вы можете догадаться из результатов теста, в Реализация CPython, __repr__ является одной из функций, которые искали тип.


В 2.x ситуация немного отличается, в основном из-за наличия классических классов, но пока вы 'только создавая классы нового стиля, вы можете думать о них как о том же.


Наиболее распространенная причина, по которой люди хотят это сделать, - это обезьяна-патч разных экземпляров объекта, чтобы делать разные вещи , Вы не можете сделать это с помощью специальных методов, так что ... что вы можете сделать? Существует чистое решение и хакерское решение.

Чистым решением является реализация специального метода в классе, который просто вызывает обычный метод для экземпляра. Затем вы можете обезьян патч использовать этот обычный метод для каждого экземпляра. Например:

class C(object):
    def __repr__(self):
        return getattr(self, '_repr')()
    def _repr(self):
        return 'Boring: {}'.format(object.__repr__(self))

c = C()
def c_repr(self):
    return "It's-a me, c_repr: {}".format(object.__repr__(self))
c._repr = c_repr.__get__(c)

Хакерное решение заключается в создании нового подкласса «на лету» и переопределении объекта. Я подозреваю, что кто-то, у кого действительно есть ситуация, когда это хорошая идея, будет знать, как его реализовать из этого предложения, и любой, кто не знает, как это сделать, не должен пытаться, поэтому я оставлю это на этом.

7
ответ дан abarnert 26 August 2018 в 13:38
поделиться

Причиной этого являются специальные методы (__x__()) определены для класса, а не для экземпляра.

Это имеет смысл, если вы думаете об __new__() - было бы невозможно назвать это на экземпляре, поскольку экземпляр не существует, когда он вызывается.

Итак, вы можете сделать это в классе в целом, если хотите:

>>> A.__repr__ = __repr__
>>> a
A

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

3
ответ дан Community 26 August 2018 в 13:38
поделиться

Для новых классов стилей Python использует специальный метод поиска, который обходит экземпляры. Здесь выдержка из источника :

  1164 /* Internal routines to do a method lookup in the type
  1165    without looking in the instance dictionary
  1166    (so we can't use PyObject_GetAttr) but still binding
  1167    it to the instance.  The arguments are the object,
  1168    the method name as a C string, and the address of a
  1169    static variable used to cache the interned Python string.
  1170 
  1171    Two variants:
  1172 
  1173    - lookup_maybe() returns NULL without raising an exception
  1174      when the _PyType_Lookup() call fails;
  1175 
  1176    - lookup_method() always raises an exception upon errors.
  1177 
  1178    - _PyObject_LookupSpecial() exported for the benefit of other places.
  1179 */

Вы можете либо перейти к классу старого стиля (не наследовать от объекта ), либо вы можете добавить методы диспетчера к классу (методы, которые перенаправляют поиск обратно в экземпляр). Пример примера методов диспетчера см. В рецепте в http://code.activestate.com/recipes/578091

3
ответ дан Raymond Hettinger 26 August 2018 в 13:38
поделиться
Другие вопросы по тегам:

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