Python 3.6 定义类中的方法和属性

本文介绍Python3中类的定义、构造方法的使用、实例化属性与共有属性的区别。通过实例详细解析类的创建过程及如何利用构造方法初始化对象。
#Python3 中类的封装,构造方法的定义,实例化属性,和共有属性

#把具有相同特征的一类东西抽象成一个类

#1,类的定义   关键字:Class

#类和方法的命名都是驼峰命名规则,但是类的首字母大写,方法的首字母小写
class  Animal(object):    #这里定义了一个Animal类,继承了object基类
    pass


#注意,任何类都会继承object基类,所以定义类的时候可以 object可写可不写

# 使用类的时候需要先实例化



an=Animal() #实例化类  现在an这个对象就得到了Animal的所有方法和属性


#2,类中构造方法的学习

class  Animal1(object):    #这里定义了一个Animal类,继承了object基类
    def __init__(self):   #这是构造方法,构造方法中必须加参数self
        print('对象只要被实例化,我就会被调用,可以把我理解成初始化方法')


a=Animal1()  #实例化Animal1类,自动输出构造方法

#实例化构造对象的时候必调用构造方法,构造方法的写法 只能是 __init__

#如果声名类的时候没有定义构造方法,那就会默认调用父类的构造方法

# __init__(self) 中的self这个参数意思是实例化对象自己

'''
#实例化对象调用类中方法的时候一定会默认传一个参数,这个默认参数就是把自己传进去
#所以说只有在类中有(self)参数的方法,才能被实例调用,
#如果类中的方法没有self参数,
#那么这个方法只能被类调用,不能被类的实例化调用
'''


#属性,实例化属性,和类属性
#类属性又叫共有属性
class Animal2(): #定义一个Animal2()类,虽然没写object 但是它默认继承
    def __init__(self,name):  #定义构造方法
        self.name=name        #这个叫实例化属性 在方法中定义的叫实例化属性

    def getName(self):
        print(self.name)     #问 为什么我getName中没有定义name属性,我可以输出
                             #因为,类在实例化的时候得到了自己的name属性,我们把self对象穿进去就有了name属性
#类属性

class Animal3(): #定义一个Animal3()类
    age=2          #这个age是共有属性
    def __init__(self,name):  #定义构造方法
        self.name=name        #这个叫实例化属性 在方法中定义的叫实例化属性

    def getName(self):
        print(self.name)  

'''
当共用属性被实例化调用的时候,共用属性会变成实例化属性,切记

'''






<think>我们正在讨论的是:在Python定义属性时如何调用方法。根据引用[4]引用[5]的内容,我们知道:-属性定义中,但在所有方法之外的变量,它属于对象,而不是的实例。-方法是使用@classmethod装饰器定义方法,它的第一个参数是cls(表示本身),通过cls可以访问属性。但是,问题是在定义属性时调用方法。注意:属性是在定义时就被初始化的,而方法也是的一部分。因此,在定义属性时,我们可能希望用方法的返回值来初始化属性。然而,在定义中,方法还没有完全创建完成,所以不能直接在属性定义行中调用方法(因为此时方法可能还没有被绑定)。但是,我们可以在定义完成后,再动态地给属性赋值(通过调用方法)。不过,如果我们希望在定义时就用方法初始化一个属性,我们可以考虑在定义之后立即执行这个操作,或者使用其他技巧。但是,有一个常见的做法:在定义中,我们可以先定义属性为None,然后在定义结束后,通过名调用方法来设置属性。但这样就不是在定义中调用了。另一种方法是使用元,但可能过于复杂。实际上,在定义内部,我们可以在属性定义之后,再通过一个方法初始化,但需要在定义完成后调用一次初始化方法似于静态块)。在Python中,我们可以利用装饰器或者在定义后立即调用一个方法。然而,我们也可以考虑在定义时直接调用方法,但是要注意:在定义过程中,方法已经可以使用了吗?在Python中,定义的过程是按顺序执行中的语句。当遇到方法(使用@classmethod装饰器)时,该方法会被创建并绑定到上。但是,在定义完成之前,这个对象还没有完全创建好,所以不能通过cls来调用。但是,在定义体内,我们可以直接通过方法名调用,但是此时它还是一个普通函数(没有绑定到上),所以我们需要将它变成静态方法?或者我们可以这样:在定义体内,方法还没有被提升为方法,它只是一个函数,直到定义完成后,装饰器才会生效。因此,在定义体内直接调用方法(在属性定义中)是不合适的,因为此时方法还没有绑定到上。但是,我们可以尝试另一种方式:在定义完成后,再定义一个属性,该属性方法计算得出。例如:```pythonclassMyClass:@classmethoddefget_default(cls):return42#在定义完成后,我们给添加一个属性default_value=get_default.__func__()#这样调用是不对的,因为此时get_default还是一个未绑定的方法(实际上,在定义体内,get_default是一个绑定到方法?不,在定义体内,方法还没有被绑定,它只是一个函数,但装饰器已经将它变成了方法?)```实际上,在定义体内,方法还没有被绑定,但是装饰器已经将它转换成了一个方法对象,我们不能直接调用它(因为它需要cls参数)。所以,在定义体内,我们不能在属性定义中直接调用方法。那么,我们如何解决呢?方法1:在定义后,通过名调用方法来设置属性。```pythonclassMyClass:@classmethoddefget_default(cls):return42MyClass.default_value=MyClass.get_default()```方法2:使用元,在元的__init__方法中设置属性(可以调用方法)。方法3:在定义一个属性,然后使用一个方法初始化,并在定义后立即调用一个初始化方法。例如:```pythonclassMyClass:default_value=None@classmethoddefinit_class(cls):cls.default_value=cls.get_default()@classmethoddefget_default(cls):return42MyClass.init_class()```但是,方法1方法3都需要在定义后额外执行代码,这可能会被忘记。方法4:使用装饰器(在定义后立即执行代码):```pythondefinit_class_attrs(cls):cls.default_value=cls.get_default()returncls@init_class_attrsclassMyClass:@classmethoddefget_default(cls):return42```方法5:在定义体内,我们可以将方法定义为静态方法(在定义属性时不需要cls),但这样它就不是方法了,而是静态方法。然后我们可以在定义属性时调用这个静态方法。但是,这不符合“方法”的要求(因为方法通常需要访问状态,而这里在定义时可能还没有其他属性)。方法6:使用__init_subclass__方法(在Python3.6+),但这是针对子初始化的。因此,根据问题的要求,我们可能需要在定义属性时调用方法,但直接调用在技术上有困难。所以,我们通常采用方法1或方法3。下面我们举一个具体的例子,采用方法1:假设我们有一个,它有一个属性`default_value`,我们希望这个属性的值是通过一个方法`get_default`计算得到的。示例代码:```pythonclassMyClass:#方法@classmethoddefget_default(cls):#这里可以有一些复杂的逻辑,比如根据名生成默认值return42#定义属性,调用方法MyClass.default_value=MyClass.get_default()#测试print(MyClass.default_value)#输出42```如果我们不想在定义后写额外的代码,我们可以使用方法3(在定义一个初始化方法,并在定义后调用):示例代码:```pythonclassMyClass:default_value=None@classmethoddefinit_class(cls):#在这里可以调用方法cls.default_value=cls.get_default()@classmethoddefget_default(cls):return42#初始化属性MyClass.init_class()print(MyClass.default_value)#42```但是,方法3需要记得调用`init_class`,如果忘记调用,属性`default_value`就还是None。方法4(装饰器)可以自动完成:```pythondefinit_class_attrs(cls):#在装饰器中调用方法初始化属性cls.default_value=cls.get_default()returncls@init_class_attrsclassMyClass:@classmethoddefget_default(cls):return42print(MyClass.default_value)#42```这样,在定义后,装饰器会自动执行,设置属性。总结:在Python中,直接在属性定义行中调用方法是困难的,因为方法定义过程中还没有绑定。我们可以采用在定义完成后通过名调用方法设置属性,或者使用装饰器、元等高级技术。根据引用[4][5],我们也可以看到属性方法的使用,但没有直接解决在定义属性时调用方法的问题。因此,我们采用了上述方法。注意:如果方法不依赖于本身的其他属性(即它可以是静态的),那么我们可以将它定义为静态方法(使用@staticmethod),然后在属性定义中直接调用,因为静态方法不需要绑定,在定义体内就可以调用。例如:```pythonclassMyClass:@staticmethoddefget_default():return42default_value=get_default()#这里直接调用静态方法,注意:这里调用的是函数,而不是方法print(MyClass.default_value)#42```但是,这要求`get_default`不需要访问属性方法(即它不依赖于状态)。如果我们需要在方法中访问本身(比如其他属性),那么静态方法就不适用。因此,根据具体情况选择合适的方法。现在,我们回到用户的问题:“我想了解如何在Python定义属性时调用方法”。我们可以给出如下答案:在Python中,直接在定义体内定义属性时调用方法是不推荐的,因为此时方法可能还未完全绑定。但我们可以通过以下方式实现似功能:1.定义后,通过名调用方法设置属性:```pythonclassMyClass:@classmethoddefget_default(cls):return42MyClass.default_value=MyClass.get_default()```2.使用装饰器:```pythondefinit_class_attrs(cls):cls.default_value=cls.get_default()returncls@init_class_attrsclassMyClass:@classmethoddefget_default(cls):return42```3.如果方法不依赖于状态,可以将其改为静态方法,然后在属性定义中直接调用:```pythonclassMyClass:@staticmethoddefget_default():return42default_value=get_default()#直接调用静态方法```请根据实际需求选择合适的方法。相关问题:1.属性实例属性有什么区别?2.Python中,方法、静态方法实例方法有何不同?3.如何使用元动态设置属性?4.装饰器在Python中是如何工作的?</think>在Python中,在定义属性时直接调用方法需要特殊处理,因为属性创建阶段初始化,而方法通常需要完全定义后才能调用。以下是几种实现方法及注意事项: ### 方法1:使用装饰器(推荐) ```python def init_class_attrs(cls): # 在装饰器内调用方法初始化属性 cls.class_attr = cls.get_class_attr_value() return cls @init_class_attrs # 装饰器 class MyClass: @classmethod def get_class_attr_value(cls): return "由方法初始化的属性值" print(MyClass.class_attr) # 输出: 由方法初始化的属性值 ``` **原理**:装饰器在定义完成后执行,此时方法已完全初始化,可直接调用[^2][^4]。 ### 方法2:定义后手动初始化 ```python class MyClass: class_attr = None # 先声明占位 @classmethod def init_class_attr(cls): cls.class_attr = cls.calculate_value() @classmethod def calculate_value(cls): return 42 * 2 # 定义完成后显式初始化 MyClass.init_class_attr() print(MyClass.class_attr) # 输出: 84 ``` **注意**:需确保在使用前调用初始化方法[^1]。 ### 方法3:元(高级用法) ```python class Meta(type): def __init__(cls, name, bases, attrs): super().__init__(name, bases, attrs) # 元初始化时设置属性 cls.class_attr = cls.generate_value() class MyClass(metaclass=Meta): @classmethod def generate_value(cls): return "元生成的属性" print(MyClass.class_attr) # 输出: 元生成的属性 ``` ### ⚠️ 重要注意事项 1. **避免在体内直接调用** 以下代码会报错(方法未完全绑定): ```python class ErrorExample: # 错误!此时get_value()尚未绑定到 class_attr = get_value() @classmethod def get_value(cls): return 42 ``` 2. **方法与静态方法的区别** - 方法(`@classmethod`)接收`cls`参数,可访问其他属性/方法[^4] - 静态方法(`@staticmethod`)无隐式参数,适合独立工具函数[^2][^3] 3. **属性的共享特性** 属性被所有实例共享,修改会影响所有实例[^5]: ```python class Shared: shared_attr = [] obj1 = Shared() obj2 = Shared() obj1.shared_attr.append(1) print(obj2.shared_attr) # 输出: [1] ``` ### 何时使用方法初始化属性? - 需要动态计算初始值(如根据环境变量) - 属性值依赖其他方法 - 需要继承时多态行为(子可重写方法) > **引用说明**: > 装饰器方案利用了Python的装饰器机制延迟执行[^2];元方案通过介入创建过程实现初始化[^1];属性共享特性源于对象在内存中的唯一性[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值