design patterns - How to do dependency injection python-way? -


i've been reading lot python-way lately question is

how dependency injection python-way?

i talking usual scenarios when, example, service needs access userservice authorization checks.

it depends on situation. example, if use dependency injection testing purposes -- can mock out -- can forgo injection altogether: can instead mock out module or class otherwise inject:

subprocess.popen = some_mock_popen result = subprocess.call(...) assert some_mock_popen.result == result 

subprocess.call() call subprocess.popen(), , can mock out without having inject dependency in special way. can replace subprocess.popen directly. (this example; in real life in more robust way.)

if use dependency injection more complex situations, or when mocking whole modules or classes isn't appropriate (because, example, want mock out 1 particular call) using class attributes or module globals dependencies usual choice. example, considering my_subprocess.py:

from subprocess import popen  def my_call(...):     return popen(...).communicate() 

you can replace popen call made my_call() assigning my_subprocess.popen; wouldn't affect other calls subprocess.popen (but replace calls my_subprocess.popen, of course.) similarly, class attributes:

class myclass(object):     popen = staticmethod(subprocess.popen)     def call(self):         return self.popen(...).communicate(...) 

when using class attributes this, necessary considering options, should take care use staticmethod. if don't, , object you're inserting normal function object or type of descriptor, property, special when retrieved class or instance, wrong thing. worse, if used right now isn't descriptor (like subprocess.popen class, in example) work now, if object in question changed normal function future, break confusingly.

lastly, there's plain callbacks; if want tie particular instance of class particular service, can pass service (or 1 or more of service's methods) class initializer, , have use that:

class myclass(object):     def __init__(self, authenticate=none, authorize=none):         if authenticate none:             authenticate = default_authenticate         if authorize none:             authorize = default_authorize         self.authenticate = authenticate         self.authorize = authorize     def request(self, user, password, action):         self.authenticate(user, password)         self.authorize(user, action)         self._do_request(action)  ... helper = authservice(...) # pass bound methods helper.authenticate , helper.authorize myclass. inst = myclass(authenticate=helper.authenticate, authorize=helper.authorize) inst.request(...) 

when setting instance attributes that, never have worry descriptors firing, assigning functions (or classes or other callables or instances) fine.


Comments

Popular posts from this blog

javascript - Enclosure Memory Copies -

php - Replacing tags in braces, even nested tags, with regex -