A.Lee
A.Lee

Reputation: 265

Any reason to put import library as class attribute?

may I know what is main reason for me to make decision if I should put datetime as class attribution or not? lets say if I know class Test2 is single class and definitely does not have plan to be inherited by any class

Is it correct to use as class Test2 does where it does not set any import as class attribute or ?

test1.py

import datetime

class Test1:
    datetime = datetime
    def getnow(self):
        return self.datetime.time()
    

test2.py

import datetime

datetime = datetime
class Test2:
    def getnow(self):
        return datetime.time()

Upvotes: 0

Views: 189

Answers (2)

jpmc26
jpmc26

Reputation: 29884

Neither of these implementations has any real benefit.

In test2.py, datetime = datetime is essentially a no-op. It does not change the state of the module. This is completely useless.

test1.py doesn't actually behave particularly differently, either. It just sets datetime as a class attribute, which means that it looks to the class to find datetime instead of the module. This might perform better in some very heavy load circumstances, but not enough that you should be worried about it unless you already know what you're doing.

The fact they invoke self.datetime.time(), though, suggests to me that the author's (assuming you saw someone doing this in their own code) intention was that datetime could be temporarily replaced at runtime, like this:

class FakeDatetime:
    def time(self):
        return 'from fake datetime'

t = Test1()
t.datetime = FakeDatetime()
print(t.getnow()) # Prints "from fake datetime"

To me, this looks like a misguided attempt to enable using a mock or stub for automated tests. They probably intend for it to be used something like this:

import unittest
from test1 import Test1

class TestStringMethods(unittest.TestCase):
    def test_my_method():
        mock = MyMock()
        expected_value = 'my value'
        # Set up code to make mock.time() return expected value

        t = Test1()
        t.datetime = mock
        assert t.time() == expected_value

The standard solution to mocking in Python is the unittest.mock module (or the mock package if using Python 3.2 or older). This module encourages patching to replace dependencies, rather than something manual like the code you presented:

test3.py

import datetime

class Test3:
    def getnow(self):
        return datetime.time()

test3tests.py

import unittest
from unittest import mock
from test3 import Test3

class TestStringMethods(unittest.TestCase):
    @mock.patch('test3.datetime')
    def test_my_method(datetime_mock):
        expected_value = 'my value'
        datetime_mock.time.return_value = expected_value

        t = Test3()
        assert t.time() == expected_value
        # Original datetime is restored by patch automatically when method exits

Upvotes: 1

S. J.
S. J.

Reputation: 76

Based on the subject did you mean?

this

import datetime

class Test1:
    datetime = datetime
    def getnow(self):
        return self.datetime.time()

vs. this

class Test2:
import datetime

    datetime = datetime
    def getnow(self):
        return self.datetime.time()

It appears your imports should be at the top of your python file. So, in that case, Test1 is the correct way to go.

In Python, what happens when you import inside of a function?

"In general practice, it's probably not that beneficial. In fact, most Python style guides encourage programmers to place all imports at the beginning of the module file."

Upvotes: 0

Related Questions