Python中的类和实例属性
在Python编程语言中, 类和实例 是面向对象编程中最重要的概念之一。实例是根据类创建的唯一对象,而类是模板。虽然数据可能会有所不同,但所有对象的过程是相同的。
在本教程中,我们将学习Python中的类、如何实例化它们、属性是什么以及类属性和实例属性之间的区别。让我们从定义开始 –
什么是类
类在Python中提供了一种将数据和功能捆绑在一起的方式。创建一个新的类就创建了一种新类型的对象,允许创建该类型的新实例。Python中的每个类实例都可以附加属性以维护其状态。类实例还可以具有修改其状态的方法(由其类定义)。
什么是实例
对象或实例
Python是一种面向对象的编程语言,强调对象,即主要强调函数。对象基本上是将数据变量和对该数据的方法封装成一个单独实体的封装体在Python中。几乎在Python中的一切都是对象,具有其属性和方法。即使当你运行“x = 5”时,实际上也是在从类’int’创建一个对象。
Python 类属性 是包含在一个类中的属性/变量。也就是说,它的作用域限于Python类内部。
Python中的类属性 仅创建一个副本 ,该副本由该类内的所有函数和对象共享和利用。
语法
class ClassName:
some_string = 'test' # this is a class attribute
同一类的所有实例都会是一样的。让我们创建两个对象并查看输出。
示例
o1 = ClassName()
o2 = ClassName()
print(ClassName.some_string)
print(o1.some_string)
print(o2.some_string)
输出
# test
# test
# test
正如清晰观察到的,类属性是 共享的 所有从其创建的对象之间。此外,类属性可以通过 class_name.attribute_name 以及 object.attribute_name 访问。属性值也可以通过 class_name.attribute_name = ‘new value’ 进行更改。
Python 实例属性 是一个本地属性/变量,其作用域在使用该属性的特定函数内。
实例属性 创建一个自己的新副本 ,每次创建一个对象时。最常用于实现此行为的函数是init()方法。
语法
class SomeClass:
def __init__(self, attr1, attr2):
self.attr1 = attr1
self.attr2 = attr2
任意数量的属性可以传递给构造函数。每个对象获取自己属性的方式可以理解为“self”在创建时引用对象,因此无法直接从类中访问“self”。
示例
obj1 = SomeClass('test', 10)
obj2 = SomeClass('hello', 15)
print(obj1.attr1, obj1.attr2)
print(obj2.attr1, obj2.attr2)
输出
# test 10
# hello 15
在这里,我们可以看到每个对象都有自己的属性值,只有对象本身可以访问到它们。
因此,更改一个对象的属性不会影响其他对象。
实例属性使用与类属性相同的点(.)符号访问。可以使用以下方式更改或重新分配它们: object_name.attribute_name = ‘new value’ 。
更改类属性的值
也许我们可以以相同的方式修改它们,毕竟为什么不呢?一个词, 继承 。
让我们举一个示例,我们定义一个函数,每次调用时将类属性的值乘以5。
示例
class ClassA:
some_string = 'test' # this is a class attribute
class_val = 2 # this is also a class attribute
def update(self):
ClassA.class_val *= 5
o1 = ClassA()
o2 = ClassA()
o1.update()
print(ClassA.class_val)
o2.update()
print(ClassA.class_val)
输出
# 10
# 50
现在让我们创建一个继承自这个类的新类。
示例
class ClassB(ClassA):
pass
new_obj = ClassB()
print(ClassA.class_val, ClassB.class_val)
new_obj.update()
print(ClassA.class_val, ClassB.class_val)
输出
# 50 50
# 250 250
为什么一个新的类对象可以改变父类的属性和自己的属性?更重要的是,如何解决这个问题?
我们写的代码有两个主要问题:
- 在ClassB的定义中使用了“pass”关键字
-
下面的代码片段 –
def update(self):
ClassA.class_val *= 5
简单地将‘pass’放在这里意味着ClassB没有自己的属性,它只是指向它的父类。其次,我们由于诱惑硬编码了类名。
另外, 调用这个函数需要首先创建一个对象,因为它期望一个‘self’引用 。相反,我们可以使用一个被称为“类方法”的东西,它有相同名称的装饰器。下面是它的样子−
@classmethod
def update(cls):
cls.class_val *= 5
它基本上表示我们只想改变调用它的那个特定类的属性。让我们举个示例来更清楚地说明一下。 最后,我们的两个类应该如下所示 –
示例
class OldClass:
some_string = 'test' # this is a class attribute
class_val = 2 # this is also a class attribute
@classmethod
def update(cls):
cls.class_val *= 5
class NewClass(OldClass):
class_val = 2 # this is different from the parent class
现在分别从两个类中调用更新函数的时间。
print("Initially:", OldClass.class_val, NewClass.class_val)
OldClass.update()
print("After calling update on old class once:",
OldClass.class_val, NewClass.class_val)
NewClass.update()
NewClass.update()
print("After calling update on new class twice:",
OldClass.class_val, NewClass.class_val)
输出
# Initially: 2 2
# After calling update on old class once: 10 2
# After calling update on new class twice: 10 50
所以,现在我们可以在Python中更改类属性而不创建对象,甚至在从父类继承之后,类方法也会知道要更改哪个类的属性。