Python变量、方法(静态、类、实例、全局、局部)超全详细解析

本文深入解析Python中的各种变量类型(全局、局部、静态、实例)及方法(静态、类、实例),并通过多个案例帮助理解不同变量的作用域及使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python变量、方法(静态、类、实例、全局、局部)超全详细解析

基础概念

a、全局变量:在模块内、在所有函数外面、在class外面,这就是全局变量。
b、局部变量:在函数内、在class的方法内(未加self修饰的),这就是局部变量
c、 静态变量:在class内的,但不在class的方法内的,这就是静态变量
d、 实例变量:在class的方法内的,用self修饰的变量,这就是实例变量

全局变量-引用

使用到的全局变量只是作为引用,不在函数中修改它的值的话,不需要加global关键字

# -*- coding:utf-8 -*-
a = 1
b = [2, 3]

def func():
    a = 2
    print "in func a:", a
    b[0] = 1
    b.append(6)
    print "in func b:", b

if __name__ == '__main__':
    print "before func a:", a
    print "before func b:", b
    func()
    print "after func a:", a
    print "after func b:", b
before func a: 1
before func b: [2, 3]
in func a: 2
in func b: [1, 3, 6]
after func a: 1
after func b: [1, 3, 6]

全局变量-修改

要修改全局变量,可以使用全局变量,之前加入global声明

a = 1
b = [2, 3]

def func():
    global a
    a = 2
    print "in func a:", a
    b[0] = 1
    print "in func b:", b

if __name__ == '__main__':
    print "before func a:", a
    print "before func b:", b
    func()
    print "after func a:", a
    print "after func b:", b
before func a: 1
before func b: [2, 3]
in func a: 2
in func b: [1, 3]
after func a: 2
after func b: [1, 3]

nonlocal

指定上一级变量,如果没有就继续往上直到找到为止

类中的各种变量

案例1 -静态方法、类方法

val1是类变量,可以由类名直接调用,也可以有对象来调用;
val2是成员变量,可以由类的对象来调用,这里可以看出成员变量一定是以self.的形式给出的,因为self的含义就是代表实例对象;
val3不是成员变量,它只是函数fcn内部的局部变量;
val4和val5也都不是成员变量,虽是以self.给出,但并没有在构造函数中初始化

静态方法:
使用装饰器@staticmethod定义静态方法。
类对象和实例都可以调用静态方法

class TestClass(object):  
    val1 = 100  #有时被认为是“python静态变量”、也称类变量

    @staticmethod
    def staticFun():
        print('这是一个静态方法')
    @classmethod
    def classFun(cls,x):
        print cls.val1*x
    def __init__(self):  
        self.val2 = 200  

    def fcn(self,val = 400):  
        val3 = 300  
        self.val4 = val  
        self.val5 = 500   
    def printLocal(self):
        print self.val5
    def printStaticValue(self):
        #print val1   #错误
        print ('printStaticValue',self.val1)
        print ('printStaticValue',TestClass.val1)


inst = TestClass()  
print TestClass.val1  
print inst.val1  
print inst.val2  

print inst.printStaticValue()

TestClass.staticFun()
TestClass.classFun(66)
#print inst.val3   #错误
#print inst.val4   #错误   
#print inst.val5   #错误
#inst.printLocal() #错误
100
100
200
('printStaticValue', 100)
('printStaticValue', 100)
None
这是一个静态方法
6600

案例2-super

Foo类必须继承某个类(并且这个继承链开始于object类),否则会报错

class Foo(object):
    def hi(self):
        print 'hi,Foo'
class Foo2(Foo):
    def hi(self):
        super(Foo2, self).hi()

if __name__ == '__main__':
    foo2 = Foo2()
    foo2.hi()
hi,Foo

案例2 类变量与实例变量

python的类变量和C++的静态变量不同,区别在于python的对象使用类变量时,会进行一次内存拷贝。python中,类本身拥有自己的类变量(保存在内存),当对象第一次调用类变量时,会将当前类变量拷贝一份给这个对象,当前类变量的值是多少,这个对象拷贝得到的类变量的值就是多少;而且,通过对象来修改类变量,并不会影响其他对象的类变量的值,因为大家都有各自的副本,更不会影响类本身所拥有的那个类变量的值;只有类自己才能改变类本身拥有的类变量的值

inst1 = TestClass()  
inst2 = TestClass()  

print TestClass.val1 # 100  
print inst1.val1     # 100  

inst1.val1 = 1000      
print inst1.val1     # 1000  
print TestClass.val1 # 100  

TestClass.val1 =2000   
print inst1.val1     # 1000  
print TestClass.val1 # 2000  

'''
inst2.val1的打印结果是2000可以发现,对象的类变量并不是构造对象的时候初始化的,
而是在第一次通过对象调用该类变量的时候从类变量当前的值拷贝过来的
'''
print inst2.val1     # 2000       

inst3 = TestClass()    
print inst3.val1     # 2000 
100
100
1000
100
1000
2000
2000
2000

案例4–list变量

class Man(object):
    #直接定义的类的变量,属于类   
    #其中 gender, avg_height为基本数据类型,immutable
    #lis为列表类型,为mutable的
    gender = 'male'   
    avg_height = 1.75
    lis = ['hello', 'world']

    def __init__(self, name):
        self.name = name  #name在类的构造函数中定义,是属于对象的变量


a = Man('jason')
b = Man('tom')

#通过一个对象a访问一个变量x,变量的查找过程是这样的:
#先在对象自身的__dict__中查找是否有x,如果有则返回,否则进入对象a所属的类A的
#__dict__中进行查找

#对象a试图修改一个属于类的 immutable的变量,则python会在内存中为对象a
#新建一个gender变量,此时a就具有了属于自己的gender变量
a.gender = 'female'

#对象b试图修改一个mutable的变量,则python找到类Man的__dict__中的变量lis,
#由于lis是可以修改的,因此直接进行修改,而不会给b新生成一个变量。类Man以及类Man
#的所有对象都公用这一个lis
b.lis = ['fuck', 'world']

print a.__dict__ #属于a的变量,有 name, gender
print b.__dict__  #属于b的变量,只有name
print Man.__dict__ #属于类Man的变量,有 gender,avg_height,lis,但是不包括 name
#name是属于对象的变量

Man.t = 'test' #此时Man的变量又多了t,但是对象a和b中没有变量t。
#(这里可以看出,对象的变量和类的变量是分开的)

print a.gender  #female
print b.gender  #male

print a.lis #['fuck', 'world']
print b.lis #['fuck', 'world']

a.addr = '182.109.23.1' #给对象a定义一个变量,对象b和类Man中都不会出现(解释性语言好随性。。)
{'gender': 'female', 'name': 'jason'}
{'name': 'tom', 'lis': ['fuck', 'world']}
{'__module__': '__main__', 'gender': 'male', '__weakref__': <attribute '__weakref__' of 'Man' objects>, 'lis': ['hello', 'world'], '__dict__': <attribute '__dict__' of 'Man' objects>, 'avg_height': 1.75, '__doc__': None, '__init__': <function __init__ at 0x00000000071587B8>}
female
male
['hello', 'world']
['fuck', 'world']

参考网址

https://www.cnblogs.com/kex1n/p/5979366.html
https://www.cnblogs.com/duanv/p/5947525.html
https://www.cnblogs.com/xixi18/p/8341828.html
https://blog.csdn.net/lc_910927/article/details/38757363
https://blog.csdn.net/cadi2011/article/details/52457754
https://www.cnblogs.com/gtarcoder/p/5005897.html

<think>好的,我现在要解决的问题是判断Python静态方法是否可以访问实例成员实例方法。我需要仔细分析用户提供的引用内容,并结合Python的相关知识来得出正确的结论。 首先,用户引用了多个资料,其中引用[1]明确指出,在静态方法中尝试访问实例属性会导致错误,因为静态方法中没有self参数。例如,代码中的self.instance_attribute会因为缺少self而报错。这说明静态方法不能直接访问实例属性。 引用[2]也提到,静态方法既不依赖实例对象也不依赖,因此无法使用实例属性方法。示例代码中试图打印self.example_name会导致错误,因为静态方法中没有self的引用。这进一步支持了静态方法不能访问实例成员的结论。 接下来,引用[3]的标题提到静态方法可以访问对象变量,但实际内容中的代码可能存在问题。例如,调用add方法时并没有访问实例变量,而是直接传递参数。这里可能存在误解,或者示例代码没有正确展示这种情况。需要仔细检查引用内容中的代码是否真的允许访问实例变量。 引用[4]指出静态方法是独立函数,不需要访问实例变量变量。示例中的add方法仅处理传入的参数,不涉及任何实例属性,这符合静态方法的定义。这说明静态方法设计上不访问实例成员。 引用[5]主要讨论方法静态方法的区别,其中静态方法没有提到可以访问实例成员,而方法使用cls参数访问属性。这也暗示静态方法不具备访问实例成员的能力。 综合这些引用,大多数资料都表明静态方法不能访问实例成员实例方法,因为它们没有接收实例的引用(如self参数)。而引用[3]的标题可能有误导,需要进一步验证。例如,是否在静态方法内部通过其他方式(如全局变量或传递实例参数)间接访问实例变量。但根据Python的语法,静态方法没有隐式的实例参数,因此直接访问实例属性是不可能的,除非显式传递实例对象进去。 例如,在静态方法中,如果传递一个实例作为参数,那么可以通过该实例访问其属性方法。但这种方式不属于静态方法自身直接访问,而是通过参数传递。例如: class MyClass: def __init__(self, value): self.value = value @staticmethod def static_method(obj): print(obj.value) obj = MyClass(10) MyClass.static_method(obj) # 输出10 这种情况下,静态方法通过参数获得实例,然后访问其属性。但这需要显式传递实例,而不是在静态方法内部直接使用self。因此,严格来说,静态方法本身无法直接访问实例成员,但可以通过参数间接访问。 总结用户的引用Python机制,结论应该是静态方法不能直接访问实例成员实例方法,因为它们没有self参数。如果需要在静态方法中使用实例属性,必须显式传递实例对象作为参数,并在方法内部通过该参数访问。但根据常规设计,静态方法通常不处理实例相关的逻辑,所以这种情况较少见。</think>Python静态方法**不允许直接访问实例成员实例方法**,具体原因如下: --- ### 一、静态方法的特性 1. **无隐式参数** 静态方法通过`@staticmethod`装饰器定义,**不自动传递实例对象(`self`)对象(`cls`)**。因此无法通过`self.xxx`访问实例成员或调用实例方法[^1][^2]。 2. **独立于实例** 静态方法本质上是**与实例解耦的普通函数**,仅寄存在中作为命名空间的工具,设计上不依赖任何实例状态[^4][^5]。 --- ### 二、错误示例分析 ```python class MyClass: def __init__(self, value): self.instance_attr = value # 实例属性 @staticmethod def static_method(): print(self.instance_attr) # 错误:静态方法中无self参数 ``` - **报错原因**:静态方法未接收`self`参数,直接访问`self.instance_attr`会触发`NameError: name 'self' is not defined`[^1][^2]。 --- ### 三、间接访问的变通方案 若需在静态方法中操作实例成员,需**显式传递实例对象作为参数**: ```python class MyClass: def __init__(self, value): self.value = value @staticmethod def static_method(obj): # 手动传入实例 print(obj.value) # 通过参数访问实例属性 obj.instance_method() # 调用实例方法 def instance_method(self): print("实例方法被调用") # 使用示例 obj = MyClass(10) MyClass.static_method(obj) # 输出: 10 \n 实例方法被调用 ``` - **局限性**:这种用法违背静态方法的设计初衷,通常建议改用**实例方法**或**方法**[^4]。 --- ### 四、与方法的对比 方法通过`@classmethod`装饰器定义,接收`cls`参数,可访问**属性**但同样不能直接访问实例属性: ```python class MyClass: class_attr = "属性" @classmethod def class_method(cls): print(cls.class_attr) # 正确:访问属性 print(self.instance_attr) # 错误:无self参数 ``` --- ### 五、设计建议 | 方法型 | 访问实例成员 | 访问成员 | 典型用途 | |--------------|--------------|------------|------------------------| | 实例方法 | ✅ (`self`) | ✅ (`self`) | 操作实例状态 | | 方法 | ❌ | ✅ (`cls`) | 工厂模式、操作属性 | | **静态方法** | ❌ | ❌ | 工具函数、逻辑分组 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值