osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Python3 - How do I import a class from another file


It might be becoming 'long', but this discussion contains much of profit 
to many people!


Us 'silver surfers' do need to periodically question those beliefs we 
hold as 'tenets' of ComSc. Amongst them is RAM (or "core"!) 
conservation. It remains a virtue somewhat, but at the same time, 
storage costs are considerably cheaper than they were four decades ago, 
whereas the relative-cost of your time (to think about such things) has 
increased!

That said, many of our more youthful (and in their own words "better in 
every way", harrumph!) colleagues should also review their own beliefs 
from time-to-time, eg working with IoT devices certainly requires a more 
conservative and considerate approach to resources!
(and in such applications, we tend to enjoy significant advantage 
because we've 'been there, done that'!)


Similarly, it is a serious fallacy to attempt to directly 'translate' a 
'command' from one language into an 'equivalent' in another/a new 
language. Whilst the syntax may appear similar, such superficiality 
doesn't allow for subtleties of meaning! In the same way, if you ask one 
person to translate the English word "preserve" into German, and then 
another person to translate that German word into English, what are the 
chances that the 'answer' will be "preserve"? Given that "preserve" 
could mean a jam/jelly/conserve (noun) or (verb) 'maintain the meaning', 
with a similar range of synonyms (etc) on the German side; the word 
"preserve" is unlikely to be preserved!
(with all due apologies for such terrible humor and word-play!)


On 9/12/19 11:32 PM, Terry Reedy wrote:
> On 12/9/2019 2:36 AM, R.Wieser wrote:
>> Terry,
>>> Standard for in-file test is
>> [snip]
>>
>> Any reason to put the testcode in a procedure instead of just have it
>> directly follow the "if __name__ == '__main__' " test ?
> 
> One can, for instance, interactively do
> 
>  >>> import mod
>  >>> mod.test()
...

I went through this cycle of thinking, first using if __name__... to 
'hide' testing, then adding test functions within the module, and now 
keep test code quite separate from 'the real thing'.

In fact, PyTest (for example) will auto-magically look for test-code in 
sub-directories of the project directory, eg "projectNM/tests". So, for 
every (Python) file in my projectDIR, you should be able to find at 
least one corresponding Python test-file in the tests sub-dir!

This fits with your philosophy of keeping (imported) modules small, 
perhaps to the point of separating each class into its own module - if 
'efficiency' is the goal, why would you want to include test-code within 
a 'production system'?


On which point, if we had a class Person(); and then decided that in 
certain cases we wanted specific methods that didn't apply to every 
(type of) Person, we would likely create a sub-class, eg class Man( 
Person ); - although some might dispute the accuracy of such an "is a" 
relationship...

That being the case, were you to put the Man class' code into (say) a 
module called "man.py" and Person()'s code into "person.py", then a 
point made earlier is that you can't merely import man.py;! You must 
also ensure that person.py is imported, somewhere along the line. Thus, 
because it names (and requires the logic of) the super-class, the 
sub-class cannot be imported 'alone'. (regardless of saving-space 
objectives, etc)


Expanding on 'names' and del(): the first point is that there is seldom 
much to be gained by using del(), ie becoming your own 'garbage 
collector'. That said, there are some very specific times when it 
becomes absolutely necessary (otherwise the Python 'gods' would not have 
given us the functionality!). Once again, RAM is (relatively) plentiful, 
and when you need to replicate many multiples of an object, it is likely 
within a loop and therefore the same instanceNM is being 're-used' and 
the garbage-collector takes care of 'recycling' the storage space 
auto-magically.


Regarding 'names', yes some languages are "strongly typed" and (mostly) 
for that reason include an indicator of "type" within the name. Python 
enables you to play fast-and-loose, eg

 >>> x = 1
 >>> x = "abc"
 >>> x = 2.3
 >>> x = [ 1, 2, 3 ]
 >>> x = ( 1, 2, 3 )
 >>> x = 1, 2, 3

constitutes a perfectly legal program (where "legal" != "useful").


There again, there are times when values are processed into a different 
data structure, eg we start with a list of values, but only want to use 
unique values/process each representative-member once.

A Python-list will handle the former (wow, that's a bit of 'rocket 
science'!?) whereas a Python-set will only contain unique values. So, 
rather than using a somewhat-bland varNM such as "letters", I would 
choose to be more explicit:

 >>> letters_list = [ "a", "b", "a", "c", "a", "d", "a" ]
 >>> len( letters_list )
7
 >>> letters_set = set( letters_list )
 >>> len( letters_set )
4
 >>> letters_set
{'b', 'a', 'd', 'c'}

There is no question whether "letters" is a list, or a set, (or ...), 
because of the explicit varNMs.

However, there are many people who dislike such an approach. Sadly, I'm 
not smart-enough to run with that crowd...


Remember that the naming conventions (mentioned elsewhere) also give you 
a hint as to type. Relevant here:

class Person(): ...	# Person is a classNM = title-case

class Man( Person ): ...	# as is Man

david = Man( etc )	# david is an instance and NOT a class (?classy)
rudy = Man( etc )	#rudy probably does have class, in this instance

del( david )	# is quite different to/separate from rudy
del( Person )	# and we know this is a class cf an instance

However, I'd question:

del( rudy )

because that might risk a tear in your space-time continuum... (!?)


-- 
Regards =dn