146 lines
5.4 KiB
Markdown
146 lines
5.4 KiB
Markdown
---
|
||
title: "Why I Prefer “import x” Over “from x import y”"
|
||
source: "https://levelup.gitconnected.com/why-i-prefer-import-x-over-from-x-import-y-b1ae8be6cbdd"
|
||
author:
|
||
- "[[Liu Zuo Lin]]"
|
||
published: 2024-05-18
|
||
created: 2024-10-29
|
||
description: "^ we can import the entire module b, and the use b.<function_name> to access the individual functions defined in b.py Here, when we use the functions defined in b.py, we need to put the module name b…"
|
||
tags:
|
||
- "clippings"
|
||
---
|
||
[
|
||
|
||

|
||
|
||
](https://zlliu.medium.com/?source=post_page---byline--b1ae8be6cbdd--------------------------------)
|
||
|
||
[
|
||
|
||

|
||
|
||
](https://levelup.gitconnected.com/?source=post_page---byline--b1ae8be6cbdd--------------------------------)
|
||
|
||

|
||
|
||
Both ways are correct, but one way is more correct than another. In my opinion, at least.
|
||
|
||
## Importing in Python
|
||
|
||
Let’s say we have 2 Python files:
|
||
|
||
- `a.py` which we run directly using the command `python a.py`
|
||
- `b.py` which contains functions that are *imported* into `a.py`
|
||
|
||
```
|
||
def test(): print('test')def hello(): print('hello')
|
||
```
|
||
|
||
^ there are 2 main ways to import the functions from `b.py` into `a.py`
|
||
|
||
## 1) import b
|
||
|
||
```
|
||
import bb.test() b.hello()
|
||
```
|
||
|
||
^ we can import the entire module `b`, and the use `b.<function_name>` to access the individual functions defined in `b.py`
|
||
|
||
Here, when we use the functions defined in `b.py`, we need to put the module name `b` beforehand eg `b.test()` or `b.hello()`
|
||
|
||
## 2) from b import <function>
|
||
|
||
```
|
||
from b import test, hellotest() hello()
|
||
```
|
||
|
||
^ alternatively, we can also use `from b import test, hello` to import the functions directly.
|
||
|
||
Here, we don’t need to put `b` before our function name — we can use the function name directly.
|
||
|
||
> Why I prefer ‘import b’ over ‘from b import test, hello’
|
||
|
||
## 1) Namespace issues
|
||
|
||
When we use `import b` instead of `from b import test, hello`, we are less likely to have a clash in namespace.
|
||
|
||
```
|
||
def test(): print('test')def hello(): print('hello')
|
||
```
|
||
```
|
||
test = 'apple'from b import test, hello
|
||
```
|
||
|
||
^ when we `from b import test, hello` inside `a.py`, we directly use the `test` and `hello` variables. If we are not careful, we might accidentally override any existing `test` and `hello` variables.
|
||
|
||
- `test` is already defined in `a.py`
|
||
- when we `from b import test`, we import `test` from `b.py`
|
||
- `test` from `b.py` overrides the original `test` from `a.py`
|
||
|
||
Note that this problem gets exponentially worse as our Python scripts become increasingly complicated, containing more and more variables that might clash with each other.
|
||
|
||
```
|
||
def test(): print('test')def hello(): print('hello')
|
||
```
|
||
```
|
||
test = 'apple'import bb.test()b.hello()
|
||
```
|
||
|
||
^ however, if we use `import b`, we need to use `b.test()` in order to access the `test` function inside `b.py`
|
||
|
||
This does not in fact clash with our original `test` variable in `a.py` as they are using different namespaces. Which means that we are much less likely to accidentally override our variables.
|
||
|
||
## 2) Less clutter
|
||
|
||
I firsthandedly experienced this recently at work.
|
||
|
||
```
|
||
def doSomethingHappily(): passdef doSomethingSadly(): passdef doSomethingAngrily(): passdef doSomethingQuickly(): passdef doSomethingSlowly(): passdef doSomethingElse(): pass
|
||
```
|
||
|
||
^ I had a bunch of functions (with pretty lengthy names) in `b.py`, and I needed to import them into `a.py`
|
||
|
||
```
|
||
from b import doSomethingHappily, doSomethingSadly, doSomethingAngrily \ doSomethingQuickly, doSomethingSlowly, doSomethingElsedoSomethingHappily()doSomethingSadly()doSomethingAngrily()doSomethingQuickly()doSomethingSlowly()doSomethingElse()
|
||
```
|
||
|
||
^ this was what my import statement was like. Some problems:
|
||
|
||
- there was lots of clutter and this took up lots of random space
|
||
- if I changed a function name, I needed to change it multiple times in `a.py` too
|
||
- which got annoying pretty quickly
|
||
|
||
Instead, I refactored my import statement to `import b`
|
||
|
||
```
|
||
import bb.doSomethingHappily()b.doSomethingSadly()b.doSomethingAngrily()b.doSomethingQuickly()b.doSomethingSlowly()b.doSomethingElse()
|
||
```
|
||
|
||
- my import statement no longer spanned multiple lines
|
||
- when I modified a function name, I no longer had to change this in multiple places
|
||
|
||
## Why not “from b import \*”?
|
||
|
||
This is bad practice, so while this is *legal* code, chances are the the senior devs might not want this around.
|
||
|
||
But why is this bad practice? `from b import *` means import *everything* from inside `b.py`. Which means we are even more likely to accidentally override some variables in our namespace now.
|
||
|
||
As good practice, we should ideally import only what we need rather than every single thing inside a module.
|
||
|
||
## Conclusion
|
||
|
||
Hope this was clear and easy to understand
|
||
|
||
## If You Wish To Support Me As A Creator
|
||
|
||
1. *Clap 50 times for this story*
|
||
2. *Leave a comment telling me your thoughts*
|
||
3. *Highlight your favourite part of the story*
|
||
|
||
*Thank you! These tiny actions go a long way, and I really appreciate it!*
|
||
|
||
**YouTube:** [**https://www.youtube.com/@zlliu246**](https://www.youtube.com/@zlliu246)
|
||
|
||
**LinkedIn:** [**https://www.linkedin.com/in/zlliu/**](https://www.linkedin.com/in/zlliu/)
|
||
|
||
**My Ebooks:** [**https://zlliu.co/ebooks**](https://zlliu.co/ebooks) |