Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Python's import work like C's #include?

Tags:

python

c

import

I've literally been trying to understand Python imports for about a year now, and I've all but given up programming in Python because it just seems too obfuscated. I come from a C background, and I assumed that import worked like #include, yet if I try to import something, I invariably get errors.

If I have two files like this:

foo.py:

a = 1

bar.py:

import foo
print foo.a
input()

WHY do I need to reference the module name? Why not just be able to write import foo, print a? What is the point of this confusion? Why not just run the code and have stuff defined for you as if you wrote it in one big file? Why can't it work like C's #include directive where it basically copies and pastes your code? I don't have import problems in C.

like image 774
Dylan LaCoursiere Avatar asked Jul 04 '26 01:07

Dylan LaCoursiere


2 Answers

To do what you want, you can use (not recommended, read further for explanation):

from foo import *

This will import everything to your current namespace, and you will be able to call print a.

However, the issue with this approach is the following. Consider the case when you have two modules, moduleA and moduleB, each having a function named GetSomeValue(). When you do:

from moduleA import *
from moduleB import *

you have a namespace resolution issue*, because what function are you actually calling with GetSomeValue(), the moduleA.GetSomeValue() or the moduleB.GetSomeValue()?

In addition to this, you can use the Import As feature:

from moduleA import GetSomeValue as AGetSomeValue
from moduleB import GetSomeValue as BGetSomeValue

Or

import moduleA.GetSomeValue as AGetSomeValue
import moduleB.GetSomeValue as BGetSomeValue

This approach resolves the conflict manually.

I am sure you can appreciate from these examples the need for explicit referencing.

* Python has its namespace resolution mechanisms, this is just a simplification for the purpose of the explanation.

like image 145
bosnjak Avatar answered Jul 05 '26 15:07

bosnjak


Imagine you have your a function in your module which chooses some object from a list:

def choice(somelist):
    ...

Now imagine further that, either in that function or elsewhere in your module, you are using randint from the random library:

a = randint(1, x)

Therefore we

import random

You suggestion, that this does what is now accessed by from random import *, means that we now have two different functions called choice, as random includes one too. Only one will be accessible, but you have introduced ambiguity as to what choice() actually refers to elsewhere in your code.

This is why it is bad practice to import everything; either import what you need:

from random import randint
...
a = randint(1, x)

or the whole module:

import random
...
a = random.randint(1, x)

This has two benefits:

  1. You minimise the risks of overlapping names (now and in future additions to your imported modules); and
  2. When someone else reads your code, they can easily see where external functions come from.
like image 28
jonrsharpe Avatar answered Jul 05 '26 16:07

jonrsharpe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!