Метод класса, который ведет себя по-другому при вызове как метод экземпляра?

Создать канал для каждой пары общающихся пользователей. Тогда не будет никакого различия между сообщениями на каналы и сообщениями для пользователей.

Я считаю удобным назвать одноранговые каналы как

[prefix][lesser_user_id][separator][greater_user_id]

Например, канал между пользователями 56789 и 12345 может быть назван chan12345.56789. В таком случае, когда вам нужно найти соответствующий канал между двумя пользователями, все, что вам нужно в качестве их идентификаторов.

26
задан Ben Blank 15 May 2009 в 00:35
поделиться

5 ответов

Сомнительно полезные хаки Python - моя сильная сторона.

from types import *

class Foo(object):
    def __init__(self):
        self.bar = methodize(bar, self)
        self.baz = 999

    @classmethod
    def bar(cls, baz):
        return 2 * baz


def methodize(func, instance):
    return MethodType(func, instance, instance.__class__)

def bar(self):
    return 4*self.baz


>>> Foo.bar(5)
10
>>> a=Foo()
>>> a.bar()
3996
39
ответ дан 28 November 2019 в 06:48
поделиться

@Unknown В чем разница между вашим и этим:

class Foo(object):

    def _bar(self, baz):
        print "_bar, baz:", baz

    def __init__(self, bar):
        self.bar = self._bar
        self.baz = bar

    @classmethod
    def bar(cls, baz):
        print "bar, baz:", baz

In [1]: import foo

In [2]: f = foo.Foo(42)

In [3]: f.bar(1)
_bar, baz: 1

In [4]: foo.Foo.bar(1)
bar, baz: 1

In [5]: f.__class__.bar(1)
bar, baz: 1
7
ответ дан 28 November 2019 в 06:48
поделиться

[отредактировано: используйте атрибут для более прямого ответа; см. полезный комментарий Джона Фухи]

Вы можете использовать дескриптор, чтобы делать то, что хотите:

class cls_or_inst_method(object):
    def __init__(self, class_method, instance_method):
        self.class_method = class_method
        self.instance_method = instance_method

    def __get__(self, obj, objtype):
        if obj is None:
            return self.class_method
        else:
            return lambda: self.instance_method(obj)

def my_class_method(baz):
    return baz + 1

def my_instance_method(self):
    return self.baz * 2

class Foo(object):
    baz = 10
    bar = cls_or_inst_method(my_class_method, my_instance_method)

Используя приведенное выше:

>>> print Foo.bar(5)
6
>>> my_foo = Foo()
>>> print my_foo.bar()
20
7
ответ дан 28 November 2019 в 06:48
поделиться

I think the larger problem is that you are overloading the name 'bar' on class 'Foo', something python doesn't allow. The second definition of 'bar' clobbers the first definition of 'bar'.

Try to think of unique names for your classmethod and instance method. i.e.

@classmethod
def create(cls, baz):
   ...

def rubber_stamp(self):
   ...
3
ответ дан 28 November 2019 в 06:48
поделиться

Вы можете переназначить свой метод идентификации в init с короткой лямбда-функцией:

class Matrix(object):
    def __init__(self):
        self.identity = lambda s=self:s.__class__.identity(s)

        #...whatever initialization code you have...
        self.size = 10        

    @classmethod
    def identity(self, other):
        #...always do you matrix calculations on 'other', not 'self'...
        return other.size


m = Matrix()
print m.identity()
print Matrix.identity(m)

Если вы не знакомы с лямбда-функцией, она создает анонимную функцию. Это редко необходимо, но может сделать ваш код более лаконичным. Приведенную выше лямбда-строку можно переписать:

    def identity(self):
        self.__class__.indentity(self)
    self.identity = identity
2
ответ дан 28 November 2019 в 06:48
поделиться
Другие вопросы по тегам:

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