Чтобы получить временную часть в формате hh:MM:ss
, вы можете использовать это регулярное выражение:
(Это было упомянуто выше в том же сообщении кем-то, спасибо за это.)
var myDate = new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
console.log(myDate)
Mixin - это особый вид множественного наследования. Существуют две основные ситуации, в которых используются миксины:
Для примера номера один рассмотрим систему запросов и ответов werkzeug . Я могу сделать простой старый объект запроса, сказав:
from werkzeug import BaseRequest
class Request(BaseRequest):
pass
Если я хочу добавить поддержку заголовка accept, я бы сделал это
from werkzeug import BaseRequest, AcceptMixin
class Request(AcceptMixin, BaseRequest):
pass
Если бы я хотел сделать запрашивать объект, поддерживающий прием заголовков, etags, проверку подлинности и поддержку пользовательского агента, я мог бы это сделать:
from werkzeug import BaseRequest, AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin
class Request(AcceptMixin, ETagRequestMixin, UserAgentMixin, AuthenticationMixin, BaseRequest):
pass
Разница тонкая, но в приведенных выше примерах классы mixin не были сделаны стоять самостоятельно. В более традиционном многократном наследовании AuthenticationMixin
(например), вероятно, будет больше похож на Authenticator
. То есть, класс, вероятно, будет создан для самостоятельной работы.
Что отличает mixin от множественного наследования? Это только вопрос семантики?
blockquote>Смесин - это ограниченная форма множественного наследования. В некоторых языках механизм добавления mixin к классу несколько отличается (в терминах синтаксиса) от наследования.
В контексте Python, особенно, mixin является родительским классом, который предоставляет функциональные возможности для подклассы, но не предназначены для создания самого себя.
Что может заставить вас сказать: «Это просто множественное наследование, а не просто mixin», если класс, который может быть запутан для mixin, может быть фактически создан и использован - так что это действительно семантика, и очень реальная разница.
Пример множественного наследования
Этот пример, из документации , является OrderedCounter:
blockquote>class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered' def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) def __reduce__(self): return self.__class__, (OrderedDict(self),)
Он подклассифицирует как
Counter
, так иOrderedDict
из модуляcollections
.Оба
Counter
иOrderedDict
предназначены для создания и использования самостоятельно. Однако, подклассифицируя их оба, мы можем иметь счетчик, который упорядочен и повторно использует код в каждом объекте.Это мощный способ повторного использования кода, но также может быть проблематичным. Если окажется, что в одном из объектов есть ошибка, исправление без забот может создать ошибку в подклассе.
Пример Mixin
Микшины обычно рекламируются как способ повторного использования кода без потенциальных проблем связи, которые могут иметь совместное множественное наследование, например OrderedCounter. Когда вы используете mixins, вы используете функциональные возможности, которые не так тесно связаны с данными.
В отличие от вышеприведенного примера, mixin не предназначен для использования сам по себе. Он предоставляет новую или различную функциональность.
Например, стандартная библиотека имеет пару миксинов в библиотеке
socketserver
.Forking и потоковые версии каждого типа сервера могут быть созданы с использованием этих классов смешения. Например, ThreadingUDPServer создается следующим образом:
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
Класс mix-in приходит первым, поскольку он переопределяет метод, определенный в UDPServer. Установка различных атрибутов также изменяет поведение базового механизма сервера.
blockquote>В этом случае методы mixin переопределяют методы в определении объекта
UDPServer
, чтобы разрешить параллелизм.Переопределенный метод представляется
process_request
, а также предоставляет другой методprocess_request_thread
. Здесь это из исходного кода :blockquote>class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" # Decides how threads will act upon termination of the # main process daemon_threads = False def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. In addition, exception handling is done here. """ try: self.finish_request(request, client_address) except Exception: self.handle_error(request, client_address) finally: self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request.""" t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()
Проприведенный пример
Это миксин, который в основном используется для демонстрационные цели - большинство объектов будут развиваться за пределами полезности этого представления:
class SimpleInitReprMixin(object): """mixin, don't instantiate - useful for classes instantiable by keyword arguments to their __init__ method. """ __slots__ = () # allow subclasses to use __slots__ to prevent __dict__ def __repr__(self): kwarg_strings = [] d = getattr(self, '__dict__', None) if d is not None: for k, v in d.items(): kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v))) slots = getattr(self, '__slots__', None) if slots is not None: for k in slots: v = getattr(self, k, None) kwarg_strings.append('{k}={v}'.format(k=k, v=repr(v))) return '{name}({kwargs})'.format( name=type(self).__name__, kwargs=', '.join(kwarg_strings) )
и использование будет:
class Foo(SimpleInitReprMixin): # add other mixins and/or extend another class here __slots__ = 'foo', def __init__(self, foo=None): self.foo = foo super(Foo, self).__init__()
И использование:
>>> f1 = Foo('bar') >>> f2 = Foo() >>> f1 Foo(foo='bar') >>> f2 Foo(foo=None)
Это не пример Python, но в языке программирования D термин mixin
используется для ссылки на конструкцию, используемую почти одинаково; добавив кучу вещей в класс.
В D (который, кстати, не делает MI) это делается путем вставки шаблона (думаю, что синтаксически осведомленные и безопасные макросы и вы будете близки) в область. Это позволяет использовать одну строку кода в классе, структуре, функции, модуле или любом другом, чтобы расширять любое количество объявлений.
OP упомянул, что он никогда не слышал о mixin в C ++, возможно, это потому, что они называются Curiously Recurring Template Pattern (CRTP) в C ++. Кроме того, @Ciro Santilli упомянул, что mixin реализован через абстрактный базовый класс в C ++. В то время как абстрактный базовый класс может использоваться для реализации mixin, он является чрезмерным, поскольку функциональность виртуальной функции во время выполнения может быть достигнута с использованием шаблона во время компиляции без накладных расходов на поиск виртуальной таблицы во время выполнения.
Схема CRTP подробно описана здесь здесь
Я преобразовал пример python в ответ @Ciro Santilli на C ++, используя шаблонный класс ниже:
#include <iostream>
#include <assert.h>
template <class T>
class ComparableMixin {
public:
bool operator !=(ComparableMixin &other) {
return ~(*static_cast<T*>(this) == static_cast<T&>(other));
}
bool operator <(ComparableMixin &other) {
return ((*(this) != other) && (*static_cast<T*>(this) <= static_cast<T&>(other)));
}
bool operator >(ComparableMixin &other) {
return ~(*static_cast<T*>(this) <= static_cast<T&>(other));
}
bool operator >=(ComparableMixin &other) {
return ((*static_cast<T*>(this) == static_cast<T&>(other)) || (*(this) > other));
}
};
class Integer: public ComparableMixin<Integer> {
public:
Integer(int i) {
this->i = i;
}
int i;
bool operator <=(Integer &other) {
return (this->i <= other.i);
}
bool operator ==(Integer &other) {
return (this->i == other.i);
}
};
int main() {
Integer i(0) ;
Integer j(1) ;
assert (i < j );
assert (i != j);
assert (j > i);
assert (j >= i);
return 0;
}
Я бы посоветовал не смешивать в новый код Python, если вы можете найти какой-либо другой способ для него (например, композиция вместо наследования или просто методы клонирования обезьян в свои собственные классы)
В классах старого стиля вы можете использовать mix-ins как способ захвата нескольких методов из другого класса. Но в мире нового стиля все, даже смешанное, наследуется от object
. Это означает, что любое использование множественного наследования естественно вводит проблемы MRO .
Существуют способы сделать работу MRO с множественным наследованием в Python, особенно в функции super (), но это означает, что вы должны выполнять всю свою иерархию классов с помощью функции super (), и значительно сложнее понять поток управления.
Этот ответ направлен на объяснение mixins примерами, которые:
It также должен рассмотреть спорный вопрос:
Требуется ли множественное наследование или не охарактеризовать mixin?
blockquote>Определения
У меня еще нет чтобы увидеть цитату из «авторитетного» источника, четко говорящего о том, что такое mixin в Python.
Я видел 2 возможных определения mixin (если их следует рассматривать как отличающиеся от других подобных понятий, таких как абстрактные базовые классы), и люди не полностью согласны с тем, какой из них правильный.
Консенсус может различаться между разными языками.
Определение 1: отсутствие множественного наследования
Mixin - это класс, так что в некотором методе класса используется метод, который не определен в классе.
Поэтому класс не предназначен для создания экземпляра, а скорее s как основной класс. В противном случае экземпляр имел бы методы, которые нельзя вызвать без привлечения исключения.
Ограничение, которое добавляют некоторые источники, состоит в том, что класс не может содержать данные, только методы, но я не понимаю, почему это необходимо , На практике, однако, многие полезные миксины не имеют никаких данных, а базовые классы без данных проще использовать.
Классическим примером является реализация всех операторов сравнения только из
<=
и==
:class ComparableMixin(object): """This class has methods which use `<=` and `==`, but this class does NOT implement those methods.""" def __ne__(self, other): return not (self == other) def __lt__(self, other): return self <= other and (self != other) def __gt__(self, other): return not self <= other def __ge__(self, other): return self == other or self > other class Integer(ComparableMixin): def __init__(self, i): self.i = i def __le__(self, other): return self.i <= other.i def __eq__(self, other): return self.i == other.i assert Integer(0) < Integer(1) assert Integer(0) != Integer(1) assert Integer(1) > Integer(0) assert Integer(1) >= Integer(1) # It is possible to instantiate a mixin: o = ComparableMixin() # but one of its methods raise an exception: #o != o
Этот конкретный пример мог быть достигнут с помощью декоратора
functools.total_ordering()
, но игра здесь заключалась в том, чтобы изобрести колесо:import functools @functools.total_ordering class Integer(object): def __init__(self, i): self.i = i def __le__(self, other): return self.i <= other.i def __eq__(self, other): return self.i == other.i assert Integer(0) < Integer(1) assert Integer(0) != Integer(1) assert Integer(1) > Integer(0) assert Integer(1) >= Integer(1)
Определение 2: множественное наследование
Mixin - это шаблон проектирования, в котором какой-либо метод базового класса использует метод, который он не определяет, и этот метод предполагается реализовать другим базовым классом , а не по производному, как в определении 1.
Термин mixin class относится к базовым классам, которые предназначены для использования в этом шаблоне проектирования (TODO те, которые используют этот метод, или те которые его реализуют?)
Нелегко решить, является ли данный класс микшированием или нет: метод может быть просто реализован в производном классе, и в этом случае мы вернемся к определению 1. Вы должны рассмотреть t авторские намерения.
Этот шаблон интересен тем, что можно рекомбинировать функциональные возможности с различными вариантами базовых классов:
class HasMethod1(object): def method(self): return 1 class HasMethod2(object): def method(self): return 2 class UsesMethod10(object): def usesMethod(self): return self.method() + 10 class UsesMethod20(object): def usesMethod(self): return self.method() + 20 class C1_10(HasMethod1, UsesMethod10): pass class C1_20(HasMethod1, UsesMethod20): pass class C2_10(HasMethod2, UsesMethod10): pass class C2_20(HasMethod2, UsesMethod20): pass assert C1_10().usesMethod() == 11 assert C1_20().usesMethod() == 21 assert C2_10().usesMethod() == 12 assert C2_20().usesMethod() == 22 # Nothing prevents implementing the method # on the base class like in Definition 1: class C3_10(UsesMethod10): def method(self): return 3 assert C3_10().usesMethod() == 13
Авторитетные вхождения Python
At официальный документ для collection.abc в документации явно используется термин Методы Mixin .
В нем указано, что если класс:
- реализует
__next__
- наследуется от одного класса
Iterator
, тогда класс получает метод
__iter__
mixin бесплатно.Поэтому, по крайней мере, в этой точке документации, mixin не требует множественного наследования и согласуется с определением 1.
Документация может быть, конечно, противоречивой в разных точках, а другие важные библиотеки Python могут использовать другое определение в своей документации.
На этой странице также используется термин
Set mixin
, в котором четко указано, что такие классы, какSet
иIterator
, могут называются классами Миксина.На других языках
- Ruby: Очевидно, не требуется множественное наследование для mixin, как указано в основных справочниках, таких как Programming Ruby и The Ruby programming Язык
- C ++: метод, который не реализован, является чистым виртуальным методом. Определение 1 совпадает с определением абстрактного класса (класса, который имеет чистый виртуальный метод). Этот класс не может быть создан. Определение 2 возможно с виртуальным наследованием: Множественное наследование от двух производных классов
mixin дает возможность добавить функциональность в класс, т. е. вы можете взаимодействовать с методами, определенными в модуле, включая модуль внутри желаемого класса. Хотя ruby не поддерживает множественное наследование, но предоставляет mixin в качестве альтернативы для достижения этого.
вот пример, который объясняет, как достигается множественное наследование с помощью mixin.
module A # you create a module
def a1 # lets have a method 'a1' in it
end
def a2 # Another method 'a2'
end
end
module B # let's say we have another module
def b1 # A method 'b1'
end
def b2 #another method b2
end
end
class Sample # we create a class 'Sample'
include A # including module 'A' in the class 'Sample' (mixin)
include B # including module B as well
def S1 #class 'Sample' contains a method 's1'
end
end
samp = Sample.new # creating an instance object 'samp'
# we can access methods from module A and B in our class(power of mixin)
samp.a1 # accessing method 'a1' from module A
samp.a2 # accessing method 'a2' from module A
samp.b1 # accessing method 'b1' from module B
samp.b2 # accessing method 'a2' from module B
samp.s1 # accessing method 's1' inside the class Sample
Может быть, пример из ruby может помочь:
Вы можете включить mixin Comparable
и определить одну функцию "<=>(other)"
, mixin предоставляет все эти функции:
<(other)
>(other)
==(other)
<=(other)
>=(other)
between?(other)
Он делает это, вызывая <=>(other)
и вернув правильный результат.
"instance <=> other"
возвращает 0, если оба объекта равны, меньше 0, если instance
больше other
и больше, чем 0, если other
больше.
Я думаю о них как о дисциплинированном способе использования множественного наследования, потому что в конечном счете mixin - это еще один класс python, который (может) будет следовать соглашениям о классах, которые называются mixins.
Мое понимание соглашения, которые управляют тем, что вы бы назвали Mixin, состоят в том, что Mixin:
object
( в Python) Таким образом, он ограничивает потенциальную сложность множественного наследования и позволяет легко отслеживать поток вашей программы, ограничивая, где вы должны смотреть (по сравнению с полным множественным наследованием ). Они похожи на рубиновые модули.
Если я хочу добавить переменные экземпляра (с большей гибкостью, чем допускается одиночным наследованием), то я склонен идти на композицию.
Сказав, что , Я видел классы, называемые XYZMixin, которые имеют переменные экземпляра.
Возможно, несколько примеров помогут.
Если вы создаете класс и хотите, чтобы он работал как словарь, вы можете определить все различные __ __
методы, необходимые. Но это немного боль. В качестве альтернативы вы можете просто определить несколько и наследовать (в дополнение к любому другому наследованию) из UserDict.DictMixin
(перемещен в collections.DictMixin
в py3k). Это приведет к автоматическому определению всего остального словаря api.
Второй пример: набор инструментов GUI wxPython позволяет создавать элементы управления списком с несколькими столбцами (например, отображение файла в Windows Explorer). По умолчанию эти списки довольно простые. Вы можете добавить дополнительные функции, такие как возможность сортировки списка по определенному столбцу, щелкнув заголовок столбца, наследуя от ListCtrl и добавляя соответствующие микшины.
Mixins - это концепция в программировании, в которой класс предоставляет функциональные возможности, но не предназначен для использования для создания экземпляра. Основная цель Mixins - предоставить функциональные возможности, которые являются автономными, и было бы лучше, если бы сами микстины не имели наследования с другими миксинами, а также избегали состояния. В таких языках, как Ruby, существует некоторая поддержка прямого языка, но для Python этого нет. Тем не менее, вы могли использовать многоуровневое наследование для выполнения функций, предоставляемых в Python.
Я смотрел это видео http://www.youtube.com/watch?v=v_uKI2NOLEM для понимания основ миксинов. Для новичков очень полезно понять основы миксинов и их работу, а также проблемы, с которыми вы можете столкнуться при их реализации.
Википедия по-прежнему остается лучшей: http: //en.wikipedia .org / вики / Mixin
Я думаю, что здесь были хорошие объяснения, но я хотел представить еще одну перспективу.
В Scala вы можете делать mixins, как описано здесь, но очень интересно, что микшины на самом деле 'fused' вместе, чтобы создать новый класс класса для наследования. По сути, вы не наследуете от нескольких классов / mixins, а скорее генерируете новый тип класса со всеми свойствами mixin для наследования. Это имеет смысл, поскольку Scala основана на JVM, где в настоящее время не поддерживается многократное наследование (с Java 8). Этот тип типа mixin, кстати, является специальным типом, называемым Trait в Scala.
Он намекает на способ определения класса: класс NewClass расширяет FirstMixin с помощью SecondMixin с ThirdMixin ...
Я не уверен, что интерпретатор CPython делает то же самое (класс-состав mixin), но я не удивлюсь. Кроме того, исходя из фона C ++, я бы не назвал ABC или «интерфейс» эквивалентным mixin - это аналогичная концепция, но расходящаяся в использовании и реализации.
Я читал, что у вас есть c # background. Поэтому хорошей отправной точкой может быть реализация mixin для .NET.
Возможно, вы захотите проверить проект codeplex в http://remix.codeplex.com/
Просмотрите ссылку lang.net Symposium, чтобы получить обзор. Еще есть информация о документации на странице Codeplex.
рассматривает Stefan
Я просто использовал микс python для реализации модульного тестирования для python milters. Как правило, milter разговаривает с MTA, что затрудняет тестирование модулей. Контрольный mixin переопределяет методы, которые говорят с MTA, и создайте имитированную среду, управляемую тестовыми примерами.
Итак, вы берете немодифицированное приложение milter, такое как spfmilter и mixin TestBase, например:
class TestMilter(TestBase,spfmilter.spfMilter):
def __init__(self):
TestBase.__init__(self)
spfmilter.config = spfmilter.Config()
spfmilter.config.access_file = 'test/access.db'
spfmilter.spfMilter.__init__(self)
Затем используйте TestMilter в тестовых примерах для приложения milter:
def testPass(self):
milter = TestMilter()
rc = milter.connect('mail.example.com',ip='192.0.2.1')
self.assertEqual(rc,Milter.CONTINUE)
rc = milter.feedMsg('test1',sender='good@example.com')
self.assertEqual(rc,Milter.CONTINUE)
milter.close()