In this short guide, you'll see the difference between dot notation and square bracket notation in Python and Pandas.

Here you can find the short answer:

(1) Dot notation for attributes

df.column_name
obj.attribute

(2) Square bracket notation for keys

df['column_name']
dict['key']

(3) When you must use brackets

df['column name with spaces']
df['2024']  # Starts with number

So let's see when to use dot notation versus square bracket notation in Python.

Suppose you have a DataFrame like:

Name Age Salary
Alice 28 75000
Bob 35 85000

1: Dot notation - Simple attribute access

Let's start with dot notation, which provides clean and readable syntax for accessing object attributes and DataFrame columns:

import pandas as pd

df = pd.DataFrame({
    'name': ['Apple Inc', 'Microsoft Corp', 'Google LLC'],
    'revenue': [394000, 211000, 307000],
    'employees': [164000, 221000, 190000]
})

print(df.name)
print(df.revenue.mean())
print(df.employees.max())

result will be:

0       Apple Inc
1    Microsoft Corp
2      Google LLC
Name: name, dtype: object

304000.0
221000

Dot notation is the preferred style when:

  • Column names are valid Python identifiers (no spaces, don't start with numbers)
  • You want cleaner, more readable code
  • Using IDE autocomplete features

What if you try to use dot notation with invalid column names? You'll get an error:

df.Apple Inc  # SyntaxError - spaces not allowed
df.2024_data  # SyntaxError - starts with number

2: Square bracket notation - Universal access method

Square bracket notation is the universal method that works with any column name or dictionary key, regardless of naming conventions:

import pandas as pd

df = pd.DataFrame({
    'Company Name': ['Amazon', 'Tesla', 'Meta'],
    '2024 Revenue': [575000, 96000, 134000],
    'Market Cap': [1800000, 850000, 950000],
    'P/E Ratio': [45.2, 68.9, 28.4]
})

print(df['Company Name'])
print(f"Average 2024 Revenue: ${df['2024 Revenue'].mean():,.0f}")
print(f"Highest Market Cap: ${df['Market Cap'].max():,.0f}")
print(f"Average P/E: {df['P/E Ratio'].mean():.1f}")

result:

0    Amazon
1     Tesla
2      Meta
Name: Company Name, dtype: object

Average 2024 Revenue: $268,333
Highest Market Cap: $1,800,000
Average P/E: 47.5

Square bracket notation is required when:

  • Column names contain spaces ('Company Name')
  • Column names start with numbers ('2024 Revenue')
  • Column names contain special characters ('P/E Ratio')
  • Accessing dictionary keys with any string
  • Column name stored in a variable

3: Working with dictionaries - Square brackets required

For Python dictionaries, you must use square bracket notation to access values:

company_data = {
    'name': 'NVIDIA Corporation',
    'ticker': 'NVDA',
    'sector': 'Technology',
    'market_cap': 1200000,
    '52_week_high': 505.89
}

print(f"Company: {company_data['name']}")
print(f"Ticker: {company_data['ticker']}")
print(f"52-Week High: ${company_data['52_week_high']}")

try:
    print(company_data.name)
except AttributeError as e:
    print(f"Error with dot notation: {e}")

result:

Company: NVIDIA Corporation
Ticker: NVDA
52-Week High: $505.89
Error with dot notation: 'dict' object has no attribute 'name'

Key point: Standard Python dictionaries don't support dot notation. Only special objects like pandas DataFrames allow both syntaxes.

4: Dynamic column access with variables

Square bracket notation is essential when column names are stored in variables or generated dynamically:

import pandas as pd

df = pd.DataFrame({
    'AAPL': [185.64, 186.89, 185.92],
    'MSFT': [372.55, 375.23, 373.89],
    'GOOGL': [145.23, 146.78, 145.67]
})

user_stock = 'AAPL'
print(f"{user_stock} prices:")
print(df[user_stock])

for ticker in ['AAPL', 'MSFT', 'GOOGL']:
    avg_price = df[ticker].mean()
    print(f"{ticker} average: ${avg_price:.2f}")

result:

AAPL prices:
0    185.64
1    186.89
2    185.92
Name: AAPL, dtype: float64

AAPL average: $186.15
MSFT average: $373.89
GOOGL average: $145.89

You cannot use dot notation with variables: df.user_stock would look for a column literally named "user_stock".

5: Pandas-specific considerations

Pandas DataFrames support both notations, but with important differences in behavior and method conflicts:

import pandas as pd

df = pd.DataFrame({
    'product': ['iPhone 15', 'Galaxy S24', 'Pixel 8'],
    'price': [999, 899, 699],
    'count': [1000, 850, 650],
    'sum': [999000, 764150, 454350]
})

print("Using dot notation:")
print(df.price.mean())

print("\nUsing square brackets:")
print(df['price'].mean())

print("\nConflict with DataFrame method 'count':")
print(type(df.count))
print(type(df['count']))

print("\nAccessing actual 'count' column:")
print(df['count'].head())

print("\nConflict with DataFrame method 'sum':")
try:
    print(df.sum.mean())
except TypeError as e:
    print(f"Error: {e}")

print("\nCorrect way:")
print(df['sum'].mean())

result:

Using dot notation:
865.6666666666666

Using square brackets:
865.6666666666666

Conflict with DataFrame method 'count':
<class 'method'>
<class 'pandas.core.series.Series'>

Accessing actual 'count' column:
0    1000
1     850
2     650
Name: count, dtype: int64

Conflict with DataFrame method 'sum':
Error: 'builtin_function_or_method' object has no attribute 'mean'

Correct way:
739166.6666666666667

Reserved pandas methods that conflict with column names:

  • count, sum, mean, max, min, std, var
  • head, tail, describe, info, shape
  • index, columns, values, dtypes
  • sort, drop, merge, join, fillna

Best practice: Always use square bracket notation for columns that might conflict with pandas methods.

6: Creating new columns - Syntax differences

When creating new columns, both notations work, but square brackets are more reliable:

import pandas as pd

df = pd.DataFrame({
    'company': ['Apple', 'Microsoft', 'Google'],
    'revenue': [394000, 211000, 307000],
    'expenses': [276000, 138000, 198000]
})

df['profit'] = df['revenue'] - df['expenses']

df.margin = (df['profit'] / df['revenue']) * 100

df['profit_margin'] = df.margin

print(df[['company', 'revenue', 'profit', 'profit_margin']])

result:

     company  revenue  profit  profit_margin
0      Apple   394000  118000      29.949239
1  Microsoft   211000   73000      34.597156
2     Google   307000  109000      35.504886

Warning: Creating columns with dot notation (df.new_col = ...) can sometimes create Python attributes instead of DataFrame columns, especially in certain contexts. Always use square brackets for column creation in production code.

7: Common errors and how to fix them

Understanding common errors helps avoid pitfalls when choosing between dot and bracket notation:

Error 1: AttributeError with dot notation

import pandas as pd

df = pd.DataFrame({
    'Customer Name': ['Apple Inc', 'Microsoft Corp'],
    'Order Value': [15000, 22000]
})

try:
    print(df.Customer Name)
except SyntaxError:
    print("SyntaxError: invalid syntax")

try:
    print(df.customer_name)
except AttributeError as e:
    print(f"AttributeError: {e}")

print("\nCorrect way:")
print(df['Customer Name'])

result:

SyntaxError: invalid syntax
AttributeError: 'DataFrame' object has no attribute 'customer_name'

Correct way:
0       Apple Inc
1    Microsoft Corp
Name: Customer Name, dtype: object

Error 2: KeyError with square brackets

import pandas as pd

df = pd.DataFrame({
    'product': ['iPhone', 'iPad'],
    'price': [999, 599]
})

try:
    print(df['Product'])
except KeyError as e:
    print(f"KeyError: {e}")

print("\nColumn names are case-sensitive:")
print(df.columns.tolist())

print("\nCorrect way:")
print(df['product'])

result:

KeyError: 'Product'

Column names are case-sensitive:
['product', 'price']

Correct way:
0    iPhone
1      iPad
Name: product, dtype: object

Error 3: Method confusion with dot notation

import pandas as pd

df = pd.DataFrame({
    'name': ['Tesla', 'Rivian'],
    'count': [500000, 50000],
    'max': [1000000, 100000]
})

print("Trying to access 'count' column with dot notation:")
print(f"Type: {type(df.count)}")

print("\nCorrect way to access 'count' column:")
print(df['count'])

print("\nTrying to access 'max' column with dot notation:")
print(f"Type: {type(df.max)}")

print("\nCorrect way to access 'max' column:")
print(df['max'])

result:

Trying to access 'count' column with dot notation:
Type: <class 'method'>

Correct way to access 'count' column:
0    500000
1     50000
Name: count, dtype: int64

Trying to access 'max' column with dot notation:
Type: <class 'method'>

Correct way to access 'max' column:
0    1000000
1     100000
Name: max, dtype: int64

Error 4: Assignment confusion

import pandas as pd

df = pd.DataFrame({'value': [10, 20, 30]})

df.new_column_dot = [100, 200, 300]

df['new_column_bracket'] = [100, 200, 300]

print("DataFrame columns:")
print(df.columns.tolist())

print("\nDataFrame contents:")
print(df)

print("\nChecking if 'new_column_dot' is in DataFrame:")
print('new_column_dot' in df.columns)

print("\nIt became a DataFrame attribute instead:")
print(hasattr(df, 'new_column_dot'))

result:

DataFrame columns:
['value', 'new_column_bracket']

DataFrame contents:
   value  new_column_bracket
0     10                 100
1     20                 200
2     30                 300

Checking if 'new_column_dot' is in DataFrame:
False

It became a DataFrame attribute instead:
True

Critical insight: Dot notation assignment creates Python attributes, not DataFrame columns. Always use square brackets to create new columns.

Comparison Table

Feature Dot Notation Square Bracket
Syntax df.column df['column']
With spaces ❌ Not allowed ✅ Works
Starts with number ❌ Not allowed ✅ Works
Special characters ❌ Not allowed ✅ Works
Variables ❌ Not supported ✅ Supported
Method conflicts ⚠️ Conflicts (count, sum, etc.) ✅ No conflicts
Column creation ⚠️ Creates attributes ✅ Creates columns
Autocomplete ✅ IDE support ⚠️ Limited
Readability ✅ Cleaner ⚠️ More verbose
Dictionaries ❌ Not supported ✅ Required

Best Practices

✅ Use square brackets in production code for reliability

✅ Use dot notation only for quick interactive analysis with simple column names

✅ Always use brackets when column names might conflict with pandas methods

✅ Always use brackets for column creation: df['new_col'] = ...

✅ Use brackets when column names might change or come from external sources

❌ Don't use dot notation for columns named after pandas methods

❌ Don't mix both styles inconsistently in the same codebase

❌ Avoid dot notation if column names aren't under your control

Common Use Cases

Data Analysis (dot notation - use with caution):

df.revenue.sum()  # Only if 'revenue' won't conflict
df.price.mean()
df.quantity.describe()

Production Code (square brackets - always safe):

df['Revenue (USD)'].sum()
df['2024 Price'].mean()
df['Order Count'].max()  # 'count' would conflict with df.count()

Dynamic Access (must use brackets):

metrics = ['revenue', 'profit', 'growth']
for metric in metrics:
    print(df[metric].describe())

Column Creation (always use brackets):

df['total'] = df['price'] * df['quantity']
df['margin'] = (df['profit'] / df['revenue']) * 100

Resources