Каково корректное (или лучше всего) способ разделить класс набора Python на подклассы, добавляя новую переменную экземпляра?

Вы можете попробовать использовать Python с пандами и пиарроу:

import pandas as pd
df = pd.read_parquet('input.parquet')
df.to_csv('out.csv', index=False)             # Exporting to CSV is easy
df.to_csv('out.txt', index=False, sep=' ')    # Text is just a tad more difficult
df.to_csv('out.txt', index=False, sep='\t')   # Alternatively, you can use tab separators
df.to_json('out.json')                        # Exporting to JSON is easy as well

См. Соответствующие документы по API:

Вы также можете изменить код выше, чтобы использовать fastparquet вместо pyarrow и проверить, дает ли это вам лучшую или худшую производительность. Все, что вам нужно изменить, - это строка, которая читает файл паркета:

df = pd.read_parquet('input.parquet', engine = 'fastparquet')

Не забудьте сначала установить pandas, pyarrow и fastparquet с помощью команды pip install pandas pyarrow fastparquet (или аналогичной, в зависимости от вашего решения по управлению пакетами ). [1 110]

13
задан rog 28 April 2009 в 15:50
поделиться

5 ответов

My favorite way to wrap methods of a built-in collection:

class Fooset(set):
    def __init__(self, s=(), foo=None):
        super(Fooset,self).__init__(s)
        if foo is None and hasattr(s, 'foo'):
            foo = s.foo
        self.foo = foo



    @classmethod
    def _wrap_methods(cls, names):
        def wrap_method_closure(name):
            def inner(self, *args):
                result = getattr(super(cls, self), name)(*args)
                if isinstance(result, set) and not hasattr(result, 'foo'):
                    result = cls(result, foo=self.foo)
                return result
            inner.fn_name = name
            setattr(cls, name, inner)
        for name in names:
            wrap_method_closure(name)

Fooset._wrap_methods(['__ror__', 'difference_update', '__isub__', 
    'symmetric_difference', '__rsub__', '__and__', '__rand__', 'intersection',
    'difference', '__iand__', 'union', '__ixor__', 
    'symmetric_difference_update', '__or__', 'copy', '__rxor__',
    'intersection_update', '__xor__', '__ior__', '__sub__',
])

Essentially the same thing you're doing in your own answer, but with fewer loc. It's also easy to put in a metaclass if you want to do the same thing with lists and dicts as well.

17
ответ дан 1 December 2019 в 20:31
поделиться

Похоже, установленный обход __ init __ в коде c . Однако вы закончите экземпляр Fooset , у него просто не будет возможности скопировать поле.

Кроме переопределения методов, которые возвращают новые наборы, я не уверен, что вы можете сделать это тоже много в этом случае. Набор четко построен для определенной скорости, поэтому много работы в c.

2
ответ дан 1 December 2019 в 20:31
поделиться

set1 | set2 - это операция, которая не изменяет ни один из существующих наборов , но вместо этого возвращает новый набор . Новый набор создан и возвращен. Невозможно заставить его автоматически копировать произвольные атрибуты из одного или обоих наборов набора во вновь созданный набор набора , не настраивая оператор | самостоятельно. Определение метода __ или __ .

class MySet(set):
    def __init__(self, *args, **kwds):
        super(MySet, self).__init__(*args, **kwds)
        self.foo = 'nothing'
    def __or__(self, other):
        result = super(MySet, self).__or__(other)
        result.foo = self.foo + "|" + other.foo
        return result

r = MySet('abc')
r.foo = 'bar'
s = MySet('cde')
s.foo = 'baz'

t = r | s

print r, s, t
print r.foo, s.foo, t.foo

Печать:

MySet(['a', 'c', 'b']) MySet(['c', 'e', 'd']) MySet(['a', 'c', 'b', 'e', 'd'])
bar baz bar|baz
2
ответ дан 1 December 2019 в 20:31
поделиться

Для меня это прекрасно работает с использованием Python 2.5.2 на Win32. Используя ваше определение класса и следующий тест:

f = Fooset([1,2,4])
s = sets.Set((5,6,7))
print f, f.foo
f.foo = 'bar'
print f, f.foo
g = f | s
print g, g.foo
assert( (f | f).foo == 'bar')

Я получаю этот вывод, что я и ожидаю:

Fooset([1, 2, 4]) default
Fooset([1, 2, 4]) bar
Fooset([1, 2, 4, 5, 6, 7]) bar
-2
ответ дан 1 December 2019 в 20:31
поделиться

Предполагая, что другие ответы верны, и переопределение всех методов - единственный способ сделать это, вот моя попытка в меру элегантного способа сделать это. Если добавлено больше переменных экземпляра, нужно изменить только один фрагмент кода. К сожалению, если новый бинарный оператор будет добавлен к объекту set, этот код сломается, но я не думаю, что есть способ избежать этого. Комментарии приветствуются!

def foocopy(f):
    def cf(self, new):
        r = f(self, new)
        r.foo = self.foo
        return r
    return cf

class Fooset(set):
    def __init__(self, s = []):
        set.__init__(self, s)
        if isinstance(s, Fooset):
            self.foo = s.foo
        else:
            self.foo = 'default'

    def copy(self):
        x = set.copy(self)
        x.foo = self.foo
        return x

    @foocopy
    def __and__(self, x):
        return set.__and__(self, x)

    @foocopy
    def __or__(self, x):
        return set.__or__(self, x)

    @foocopy
    def __rand__(self, x):
        return set.__rand__(self, x)

    @foocopy
    def __ror__(self, x):
        return set.__ror__(self, x)

    @foocopy
    def __rsub__(self, x):
        return set.__rsub__(self, x)

    @foocopy
    def __rxor__(self, x):
        return set.__rxor__(self, x)

    @foocopy
    def __sub__(self, x):
        return set.__sub__(self, x)

    @foocopy
    def __xor__(self, x):
        return set.__xor__(self, x)

    @foocopy
    def difference(self, x):
        return set.difference(self, x)

    @foocopy
    def intersection(self, x):
        return set.intersection(self, x)

    @foocopy
    def symmetric_difference(self, x):
        return set.symmetric_difference(self, x)

    @foocopy
    def union(self, x):
        return set.union(self, x)


f = Fooset([1,2,4])
f.foo = 'bar'
assert( (f | f).foo == 'bar')
0
ответ дан 1 December 2019 в 20:31
поделиться
Другие вопросы по тегам:

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