Code With Globals
Code With Globals
import builtins
s = "hello"
x = 10
original_len = builtins.len # Backup built-in len
def len(y):
print("Inside custom len()")
print("Locals inside len():")
print(locals()) # Show local variables inside len
def inner():
print("Inside inner function")
print("Locals inside inner():")
print(locals()) # Show inner's local scope
inner()
return y
Sample Output:
Globals at the start:
dict_keys(['__name__', '__doc__', ..., 's', 'x', 'original_len', 'len', 'builtins'])
10
def len(y):
...
You've redefined len in your current (global) namespace. From that point on, when you call len(),
you're calling your version, not the built-in one.
When you call len(s), Python looks for len in this order:
So if your code has a global len, Python never looks further into the built-in len.
Why We Do This:
original_len = builtins.len
So that even after redefining len, we can still access the real one:
print(original_len("hello")) # Safely calls the built-in version
Example:
print(len("hello")) # built-in len
def len(x):
return "I shadowed the built-in!"
Output:
5
I shadowed the built-in!
Best Practice:
note: But in real-world projects, avoid naming functions or variables the same as built-ins (len,
sum, list, etc.).
__name__ is a special built-in variable in Python that indicates how a Python script is being used
— either:
If you run your Python file directly (e.g., python myfile.py), Python sets:
__name__ = "__main__"
import myfile
Then:
python
CopyEdit
__name__ = "myfile"
It allows you to control what code runs when the file is used as a script vs. when it's imported:
def greet():
print("Hello!")
if __name__ == "__main__":
greet() # This will only run when the file is executed directly
Summary:
When you call methods like .keys(), .values(), or .items() on a dictionary, they return view objects.
Example:
my_dict = {'a': 1, 'b': 2}
keys_view = my_dict.keys()
print(keys_view) # dict_keys(['a', 'b'])
my_dict['c'] = 3
print(keys_view) # dict_keys(['a', 'b', 'c']) – reflects the change
So, a view object is just a live, read-only window into the dictionary’s keys, values, or items.
my_dict = {'x': 1}
print(type(my_dict.keys())) # <class 'dict_keys'>
✅ Example:
my_dict = {'a': 1, 'b': 2}
keys_view = my_dict.keys() # view object created
You did not call .keys() again — but the keys_view reflected the change. That’s why it’s dynamic: it stays
linked to the dictionary, not a snapshot copy.
Summary:
Feature Explanation
✅ Example:
x = 10
print(type(x)) # <class 'int'>
s = "hello"
print(type(s)) # <class 'str'>
lst = [1, 2, 3]
print(type(lst)) # <class 'list'>
For example:
s = "hello"
print(s.upper()) # Outputs: HELLO
Summary:
Concept Meaning
class MyString:
def upper(self):
s = MyString("hello")
Explanation:
self.data holds the actual content — similar to how "hello" is stored in a str object.
upper() is a method, just like built-in string objects have.
The object s behaves like a simple version of a real Python string object.