Я использовал https://github.com/facebookgo/inject для DI и https://github.com/golang/mock для насмешек. Например:
// some_entity_dao.go
type SomeEntity interface {
Find(ctx context.Context, condition *model.SomeEntity) (*model.SomeEntity, error)
FindAll(ctx context.Context, condition *model.SomeEntity) ([]*model.SomeEntity, error)
Save(ctx context.Context, data *model.SomeEntity) error
Update(ctx context.Context, condition *model.SomeEntity, data *model.SomeEntity) error
Delete(ctx context.Context, condition *model.SomeEntity) error
}
И сгенерировать фиктивную реализацию, используя:
//go:generate mockgen -source=./some_entity_dao.go -destination=./some_entity_dao_mock_impl.go -package dao
Затем используйте эту фиктивную реализацию при написании юнит-тестов.
Учитывая Ваши требования, я сказал бы, что пользовательский класс является Вашим лучшим выбором:
class options(object):
VERBOSE = True
IGNORE_WARNINGS = True
if options.VERBOSE:
# ...
Чтобы быть завершенным, другой подход использовал бы отдельный модуль, т.е. options.py
инкапсулировать Ваши значения по умолчанию опции.
options.py
:
VERBOSE = True
IGNORE_WARNINGS = True
Затем в main.py
:
import options
if options.VERBOSE:
# ...
Это имеет функцию удаления некоторой помехи из Вашего сценария. Значения по умолчанию легко найти и измениться, поскольку они загорожены в их собственном модуле. Если позже Ваше приложение выросло, можно легко получить доступ к опциям от других модулей.
Это - шаблон, который я часто использую и сердечно рекомендовал бы, если Вы не возражаете против своего приложения, растущего, чем единственный модуль. Или, запустите с пользовательского класса и расширьтесь до модуля позже, если Ваше приложение растет до нескольких модулей.
Модуль наборов вырастил функцию namedtuple в 2,6:
import collections
opt=collections.namedtuple('options','VERBOSE IGNORE_WARNINGS')
myoptions=opt(True, False)
>>> myoptions
options(VERBOSE=True, IGNORE_WARNINGS=False)
>>> myoptions.VERBOSE
True
namedtuple неизменен, таким образом, можно только присвоить значения полей при создании его.
В более ранних версиях Python можно создать пустой класс:
class options(object):
pass
myoptions=options()
myoptions.VERBOSE=True
myoptions.IGNORE_WARNINGS=False
>>> myoptions.IGNORE_WARNINGS,myoptions.VERBOSE
(False, True)
Почему не просто используют optparse:
from optparse import OptionParser
[...]
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
file = options.filename
if options.quiet == True:
[...]
Если Вы настаиваете на том, чтобы не иметь необходимость определить класс, можно злоупотребить некоторыми существующими классами. Большинство объектов принадлежит "модернизированным" классам, которые не имеют dict, но функции могут иметь произвольные атрибуты:
>>> x = lambda: 0 # any function will do
>>> x.foo = 'bar'
>>> x.bar = 0
>>> x.xyzzy = x
>>> x.foo
'bar'
>>> x.bar
0
>>> x.xyzzy
<function <lambda> at 0x6cf30>
Одна проблема состоит в том, что функции уже имеют некоторые атрибуты, таким образом, dir (x) немного грязен:
>>> dir(x)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__',
'__get__', '__getattribute__', '__hash__', '__init__',
'__module__', '__name__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', 'foo',
'func_closure', 'func_code', 'func_defaults', 'func_dict',
'func_doc', 'func_globals', 'func_name', 'xyzzy']
Просто сделайте модуль по имени Options.py и импортируйте его. Поместите свои значения опций по умолчанию там как глобальные переменные.
Я использую attrdict:
class attrdict(dict):
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
self.__dict__ = self
В зависимости от Вашей точки зрения Вы, вероятно, думаете, что это - или большой клудж или довольно умный. Но независимо от того, что Вы думаете, это действительно делает для симпатичного кода и совместимо с dict:
>>> ad = attrdict({'foo': 100, 'bar': 200})
>>> ad.foo
100
>>> ad.bar
200
>>> ad.baz = 'hello'
>>> ad.baz
'hello'
>>> ad
{'baz': 'hello', 'foo': 100, 'bar': 200}
>>> isinstance(ad, dict)
True
Когда лучшие практики идут, Вы действительно более обеспечены с одной из опций в ответе David Eyk.
Однако для ответа на вопрос можно создать одноразовый класс с помощью type
функция:
options = type('Options', (object,), { 'VERBOSE': True })()
options.IGNORE_WARNINGS = False
Обратите внимание, что можно предоставить первоначальный словарь, или просто оставить это пустым.
Options = type('Options', (object,), {})
options = Options()
options.VERBOSE = True
options.IGNORE_WARNINGS = False
Не очень pythonic.
Упрощая предложение davraamides, можно было использовать следующее:
class attrdict2(object):
def __init__(self, *args, **kwargs):
self.__dict__.update(*args, **kwargs)
который
Не таким образом топорен.
Не загрязняет пространство имен каждого объекта со стандартными методами dict
; например, ad.has_key
не определяется для объектов типа attrdict2
.
Между прочим, еще легче инициализировать экземпляры attrdict
или attrdict2
:
>>> ad = attrdict2(foo = 100, bar = 200)
Предоставленный, attrdict2
не совместимо с a dict
.
Если Вам не нужно волшебное поведение инициализации, можно даже использовать
class attrdict3(object):
pass
ad = attrdict3()
ad.foo = 100
ad.bar = 200
Но я все еще надеялся на решение, которое не требует вспомогательного класса.
Можно использовать
class options(object):
VERBOSE = True
IGNORE_WARNINGS = False
options.VERBOSE = False
if options.VERBOSE:
...
, использование самого объекта класса (не экземпляр класса!) как место для хранения отдельных опций. Это кратко и удовлетворяет все требования, но это походит на неправильное употребление понятия класса. Это также привело бы к беспорядку если пользователь, который инстанцируют options
класс.
(Если бы несколько экземпляров содержащих опции объектов были необходимы, то это было бы очень хорошим решением - определение класса предоставляет значения по умолчанию, которые могут быть переопределены в отдельных экземплярах.)
Абсолютно самый простой класс, чтобы сделать задание:
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
Это может позже использоваться как:
john = Struct(name='john doe', salary=34000)
print john.salary
namedtuple
(как другой прокомментировал предложенный), более усовершенствованный класс, который дает Вам больше функциональности. Если Вы все еще используете Python 2.5, реализация 2.6's namedtuple
на основе, может быть найден по http://code.activestate.com/recipes/500261/