python Тестирование confluent_kafka Потребительский [дубликат]

Я бы не сделал это. Мое правило: методы предоставления услуг со всем, что им нужно для выполнения своей работы, и ничего больше .

Почему?

  1. Потому что он уменьшает сцепление. Чаще всего методы обслуживания адресованы из нескольких источников (потребителей). Пользователю намного проще выполнить простую сигнатуру метода, чем создавать относительно сложный объект, такой как модель представления, иначе он не имеет никакого отношения. Это может даже потребоваться ссылка на сборку, в которой она не понадобится.
  2. Это значительно снижает затраты на техническое обслуживание. Я думаю, что средний разработчик тратит более 50% своего времени на проверку и отслеживание существующего кода (возможно, даже гораздо больше). Теперь всем известно, что поиск чего-то, что не , занимает непропорционально много времени: вы наверняка были везде . Если метод получает аргументы (или объекты со свойствами), которые не используются напрямую или дальше в стеке вызовов, вы или другие люди будете ходить по этому длинному пути и снова.

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

44
задан Lii 7 May 2018 в 12:18
поделиться

14 ответов

Что именно вы подразумеваете под патчем Monkey здесь? Есть несколько несколько разных определений .

Если вы имеете в виду, «можете ли вы изменить методы класса во время выполнения?», Тогда ответ решительно да:

class Foo:
  pass # dummy class

Foo.bar = lambda self: 42

x = Foo()
print x.bar()

Если вы имеете в виду: «Можете ли вы изменить методы класса во время выполнения и сделать все экземпляры этого класса после факта?» тогда и ответ да. Просто немного измените порядок:

class Foo:
  pass # dummy class

x = Foo()

Foo.bar = lambda self: 42

print x.bar()

Но вы не можете сделать это для определенных встроенных классов, например int или float. Эти методы классов реализованы в C, и некоторые абстракции пожертвованы, чтобы сделать реализацию проще и эффективнее.

Я не совсем понимаю, почему вы хотели бы изменить поведение встроенного - В числовых классах все равно. Если вам нужно изменить свое поведение, подклассируйте их !!

36
ответ дан Dan Lenski 15 August 2018 в 16:46
поделиться

Вы можете это сделать, но это требует немного взлома. К счастью, теперь есть модуль, называемый «Forbidden Fruit», который дает вам возможность исправлять методы встроенных типов очень просто. Вы можете найти его в

http://clarete.github.io/forbiddenfruit/?goback=.gde_50788_member_228887816

или

https://pypi.python.org/pypi/forbiddenfruit/0.1.0

С исходным вопросом вопроса после того, как вы напишете функцию «should_equal», вы просто сделайте

from forbiddenfruit import curse
curse(int, "should_equal", should_equal)

, и вам хорошо идти! Существует также функция «обратного» удаления исправленного метода.

22
ответ дан alcalde 15 August 2018 в 16:46
поделиться
  • 1
    интересная библиотека модулей python – dreftymac 4 September 2013 в 05:50
  • 2
    Кажется странным. Некоторые вещи, которые я стараюсь, работают отлично. Другие вещи, которые я пытаюсь, кажутся просто проигнорированными. Невозможно найти шаблон, рифму или причину. – ArtOfWarfare 3 July 2015 в 22:25

Нет, к сожалению, вы не можете расширять типы, реализованные в C во время выполнения.

Вы можете подклассировать int, хотя это нетривиально, вам может потребоваться переопределить __new__.

У вас также есть проблема с синтаксисом:

1.somemethod()  # invalid

Однако

(1).__eq__(1)  # valid
2
ответ дан Dima Tisnek 15 August 2018 в 16:46
поделиться

Вот как я могу достичь .should_something ... поведения:

result = calculate_result('blah') # some method defined somewhere else

the(result).should.equal(42)

или

the(result).should_NOT.equal(41)

Я включил метод декоратора для расширения этого поведения во время выполнения на стенде -alone method:

@should_expectation
def be_42(self)
    self._assert(
        action=lambda: self._value == 42,
        report=lambda: "'{0}' should equal '5'.".format(self._value)
    )

result = 42

the(result).should.be_42()

Вы должны знать немного о внутренних элементах, но он работает.

Вот источник:

https: //github.com/mdwhatcott/pyspecs

Он также находится в PyPI под pyspecs.

0
ответ дан guneysus 15 August 2018 в 16:46
поделиться

Если вы действительно действительно хотите сделать патч обезьяны в Python, вы можете сделать (sortof) взломать с помощью метода «import foo as bar».

Если у вас есть класс, такой как TelnetConnection, и вы хотите его расширить, подклассифицируйте его в отдельный файл и назовите его чем-то вроде TelnetConnectionExtended.

Затем в верхней части вашего кода, где вы обычно говорите:

import TelnetConnection

измените это значение:

import TelnetConnectionExtended as TelnetConnection

, а затем всюду в вашем коде, который вы ссылаетесь на TelnetConnection, действительно будет ссылаться на TelnetConnectionExtended.

К сожалению, это предполагает, что у вас есть доступ к этому классу, а «как» работает только в этом конкретном файле (это не глобальное переименование), но я нашел его полезным время от времени.

3
ответ дан HanClinto 15 August 2018 в 16:46
поделиться

Нет, вы не можете. В Python все данные (классы, методы, функции и т. Д.), Определенные в модулях расширения C (включая встроенные), неизменяемы. Это связано с тем, что C-модули совместно используются несколькими интерпретаторами в одном и том же процессе, поэтому monkeypatching them также влияет на несвязанных интерпретаторов в одном и том же процессе.

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

61
ответ дан John Millikin 15 August 2018 в 16:46
поделиться
  • 1
    Хотя делать вещи неизменными ради эффективности имеет смысл, было бы неплохо, если бы Python отреагировал на попытки изменить эти неизменные встроенные классы, заменив только изменчивую версию только в этом интерпретаторе. Таким образом, нормальный случай был бы неизменным со всеми преимуществами производительности, но если вы хотите сделать исключение, вы можете. В некоторых случаях производительность не так важна. Я смотрю на вас, класс datetime и отсутствие встроенных методов. – Alexander Ljungberg 7 October 2010 в 21:23
  • 2
    Ah - копия на основе стиля записи. Это был бы аккуратный способ поведения - но в основном специализированный сервис для насмешек / тестирования и в большинстве других случаев - не было бы более сложным подклассификация? – Danny Staple 17 August 2012 в 17:33
  • 3
    IE этот ответ - stackoverflow.com/a/5437199/490188 – Danny Staple 17 August 2012 в 17:47
  • 4
    С каких это пор вы могли бы иметь несколько интерпретаторов Python в одном процессе? Я не думаю, что вы можете даже иметь это с Python, встроенным в другую программу; реализация только позволяет. – user2357112 30 March 2017 в 19:11
  • 5
    Я не думаю, что в этом ответе есть какая-то основа. – user2357112 30 March 2017 в 19:33
  • 6
    – user2357112 7 October 2018 в 03:39
def should_equal_def(self, value):
    if self != value:
        raise ValueError, "%r should equal %r" % (self, value)

class MyPatchedInt(int):
    should_equal=should_equal_def

class MyPatchedStr(str):
    should_equal=should_equal_def

import __builtin__
__builtin__.str = MyPatchedStr
__builtin__.int = MyPatchedInt

int(1).should_equal(1)
str("44").should_equal("44")

Удачи;)

25
ответ дан Jonathan 15 August 2018 в 16:46
поделиться
  • 1
    Почему это неправильно? – Andrew Burns 1 March 2011 в 20:08
  • 2
    Я не думаю, что это неправильно по той же причине @JakobBowyer, возможно, в конце концов, это то, о чем просит наш Rubyist OP, но требующий использования встроенных конструкторов str () и int () sucks = ( – Matt Luongo 19 October 2011 в 17:27
  • 3
    Его очень неправильно, потому что он заставляет программистов других проектов хотеть, чтобы вы умерли. Представьте, что я импортирую вашу библиотеку большой задницы, и вы monkeypatch int. Теперь, что произойдет, если int не ведет себя так, как я ожидаю? – Jakob Bowyer 21 October 2011 в 15:20
  • 4
    @JakobBowyer Я думаю, что это очень неправильно, только когда вы используете from HisPatch import * – Hanfei Sun 19 February 2013 в 13:44
  • 5
    @Firegun Проблема в том, что any импорт из HisPatch приведет к выполнению этого кода и глобально изменить встроенные классы. Не то, чтобы я не рассматривал использование чего-то вроде этого ... – Tobias Kienzler 8 December 2014 в 14:05

Нет, но у вас есть UserDict UserString и UserList, которые были сделаны именно с этим.

Если вы используете Google, вы найдете примеры для других типов, но это встроенные функции.

В общем, патч обезьяны менее используется в Python, чем в Ruby.

1
ответ дан Luka Marinko 15 August 2018 в 16:46
поделиться

Вы не можете изменять основные типы в python. Однако вы можете использовать трубу для написания более понятного для человека кода:

from pipe import *

@Pipe
def should_equal(obj, val):
    if obj==val: return True
    return False

class dummy: pass
item=dummy()
item.value=19.99

print item.value | should_equal(19.99)
7
ответ дан Lvsoft 15 August 2018 в 16:46
поделиться
  • 1
    Приятно, спасибо! Вот страница проекта Pipe на PyPI: pypi.python.org/pypi/pipe – michel-slm 31 May 2012 в 11:03
  • 2
    Хорошее дополнение, хотя это не относится к основному питону, поэтому у него есть недостатки для людей, которым не разрешено импортировать пользовательские библиотеки – dreftymac 4 September 2013 в 05:42

Кажется, что вы действительно хотели написать:

assert item.price == 19.99

(Конечно, сравнение float для равенства или использование float для цен - это плохая идея , поэтому вы напишете assert item.price == Decimal(19.99) или какой-нибудь цифровой класс, который вы использовали для цены.)

Вы также можете использовать платформу тестирования, например py.test , чтобы получить дополнительную информацию о сбоях утверждает в ваших тестах.

1
ответ дан Petr Viktorin 15 August 2018 в 16:46
поделиться

Вот пример реализации item.price.should_equal, хотя я бы использовал Decimal вместо float в реальной программе:

class Price(float):
    def __init__(self, val=None):
        float.__init__(self)
        if val is not None:
            self = val

    def should_equal(self, val):
        assert self == val, (self, val)

class Item(object):
    def __init__(self, name, price=None):
        self.name = name
        self.price = Price(price)

item = Item("spam", 3.99)
item.price.should_equal(3.99)
4
ответ дан Ryan Ginstrom 15 August 2018 в 16:46
поделиться

Нет, вы не можете сделать это в Python. Я считаю, что это хорошо.

1
ответ дан sanxiyn 15 August 2018 в 16:46
поделиться

Что делает should_equal? Это логическое возвращение True или False? В этом случае это написано:

item.price == 19.99

У вас нет учета вкуса, но обычный разработчик python не сказал бы, что это менее читаемо, чем ваша версия.

Установил ли should_equal какой-то валидатор? (почему валидатор должен быть ограничен одним значением? Почему бы просто не установить значение и не обновить его после этого?) Если вы хотите валидатор, это никогда не сможет работать в любом случае, так как вы предлагаете изменить либо определенное целое число, либо все целые числа. (Валидатор, который требует 18.99 равным 19.99, всегда терпит неудачу.) Вместо этого вы могли бы записать его следующим образом:

item.price_should_equal(19.99)

или это:

item.should_equal('price', 19.99)

и определить соответствующие методы класса или суперклассов.

1
ответ дан user 15 August 2018 в 16:46
поделиться

Основные типы Python неизменяемы по дизайну, как указывают другие пользователи:

>>> int.frobnicate = lambda self: whatever()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'

Вы, конечно, могли бы добиться эффекта, который вы описываете, создавая подкласс, поскольку пользователь Определенные типы в Python по умолчанию изменяются.

>>> class MyInt(int):
...   def frobnicate(self):
...     print 'frobnicating %r' % self
... 
>>> five = MyInt(5)
>>> five.frobnicate()
frobnicating 5
>>> five + 8
13

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

Конечно, есть несколько ситуаций, когда программисты Python, свободно владеющие идиомой, считают, что этот класс подкласса правилен делать. Например, os.stat() возвращает подкласс tuple, который добавляет именованные члены, точно для того, чтобы устранить проблему с точки зрения удобочитаемости, о которой вы говорите в своем примере.

>>> import os
>>> st = os.stat('.')
>>> st
(16877, 34996226, 65024L, 69, 1000, 1000, 4096, 1223697425, 1223699268, 1223699268)
>>> st[6]
4096
>>> st.st_size
4096

Тем не менее, в конкретном пример, который вы даете, я не считаю, что подклассификация float в item.price (или в другом месте) с большой вероятностью будет считаться питонической задачей. I может легко представить, что кто-то решил добавить метод price_should_equal() к item, если это был основной случай использования; если бы кто-то искал что-то более общее, возможно, было бы разумнее использовать именованные аргументы, чтобы сделать предполагаемый смысл более ясным, как в

should_equal(observed=item.price, expected=19.99)

или что-то в этом направлении. Это немного многословно, но, без сомнения, его можно было бы улучшить. Возможным преимуществом такого подхода по сравнению с рубиновым обезьян-патчем является то, что should_equal() может легко выполнить сравнение по любому типу, а не только int или float. Но, возможно, я слишком зациклен на деталях конкретного примера, который вам удалось предоставить.

13
ответ дан zaphod 15 August 2018 в 16:46
поделиться
Другие вопросы по тегам:

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