赞
踩
在Python中,类是一种用于创建新类型对象的结构,它允许我们将数据和功能(属性和方法)封装到一个单独的逻辑单元中。类可以被看作是创建对象(实例)的蓝图或模板。类(Class)和对象(Object)是面向对象编程(OOP)的核心概念。
类是一个用于创建对象的模板或蓝图。它定义了一组属性和方法,这些属性和方法将被它创建的对象所共享。类本质上是一种数据结构,它封装了数据以及操作这些数据的函数。
通过定义一个类,你实际上是在定义一种新类型的数据结构,这种结构包含了特定类型、对象所具有的属性、可以对这些属性执行哪些操作。
对象是根据类被创建出来的实例。每个对象都拥有独立于其他对象的属性值集合,但所有对象都共享同一个方法集合(即那些在其对应类中被定义过)。简单来说:
一个基本的类定义包括关键字class
,后面跟着类名和冒号。在其下方缩进的代码块中,可以定义属性(变量)和方法(函数)。
要使用一个类,你需要根据该类创建对象。每个对象都会有自己独立的属性集合。
class MyClass: def __init__(self, value): # 特殊方法__init__用于初始化对象,构造器 self.my_attribute = value def my_method(self): return self.my_attribute * 2 # 实例化对象 obj = MyClass(99) print(obj) print(obj.my_method()) print(obj.my_attribute) # 直接修改对象的属性 obj.my_attribute = 100 print(obj) print(obj.my_method()) print(obj.my_attribute)
驼峰命名法:Python中的类名通常使用驼峰命名法(CamelCase)。这意味着类名中每个单词的首字母都大写,而且单词之间不使用下划线分隔。例如,MyClass
、DataProcessor
、CarEngine
。
描述性命名:类名应该简洁且富有描述性,清楚地表明类的用途或功能。例如,避免使用模糊的名称如Foo
或Bar
,而应选择更具描述性的名称,如Customer
、EmailParser
。
避免缩写:尽量避免使用缩写,因为缩写可能会使代码的可读性降低。完整的单词能更好地表达类的意图和功能。
首字母大写:按照Python的约定,类名的首字母应该大写,即使它是一个缩写。例如,URLParser
而不是urlParser
。
避免使用内置类型名称:避免使用像str
、list
或dict
这样的Python内置类型名称作为类名,以免造成混淆。
命名长度:虽然没有硬性的长度限制,但一般推荐类名不要过长,以保持代码的清晰和易于维护。
Python提供了多个特殊方法(也称为魔术方法),它们由双下划线包围。这些特殊方法提供了与Python语言功能集成的方式。
__init__(self, [...])
: 对象初始化方法,在创建新实例后被调用。__new__(cls, [...])
: 实际的对象构造函数,是一个静态方法,在__init__
之前被调用。class TestClassMethod: # 定义变量,如果不赋值则必须指定类型 # 但是类型注解 value_a: int 表示期望 value_a 是一个整数类型,但它并不会阻止你将其他类型赋给该属性。 value_a: int value_b = "value_b" # 初始化方法 def __init__(self, init_value: int): # 类型注解本身并不会强制变量类型,在运行时仍然可以给带有类型注解的变量赋予任何类型的值。 print(f'初始化方法调用... init_value : {init_value}') # 如果不指定 self. 则为局部变量,无法在这里赋值 # value_a = init_value self.value_a = init_value # 实际的对象构造函数,是一个静态方法,在__init__之前被调用。 # 在生产环境编写代码时通常不需要自己手动重写 __new__ 方法;除非你需要控制对象创建过程。对于大多数情况,默认行为已经足够。 @staticmethod # 名为 __new__ 的实例方法并非特殊方法。特殊方法 __new__ 应当被定义为静态方法(使用装饰器 @staticmethod),或者更常见地作为类方法(使用装饰器 @classmethod)。 def __new__(cls, *args, **kwargs): print(f'对象构造函数调用... cls : {cls}') return super(TestClassMethod, cls).__new__(cls) method = TestClassMethod(1) print(method.value_a) # 虽然类中定义了类型为int,但是照常可以赋值字符串 method.value_a = 'aa' print(method.value_a) print(method.value_b) print(dir(method))
__repr__(self)
: 定义对象的“官方”字符串表示。__str__(self)
: 定义对象的“非正式”或可打印字符串表示。__format__(self, format_spec)
: 定义当使用format()
函数时对象的格式。__repr__(self)
repr()
时;当没有定义__str__
时,在使用print函数打印对象或者在解释器中直接输入变量名查看对象时;还有就是在调试过程中经常会看到这个表示。class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
__str__(self)
str()
或者使用print函数打印一个对象时。class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Point located at ({self.x}, {self.y})"
虽然两者都提供了关于对象信息展示方式,但主要区别在于目标受众和它们各自所承担角色:
__repr__
: 面向开发者和调试器。其目标是明确无误地表达出如何构造出相同数据内容的新实例。__str__
: 面向最终用户。其目标是提供友好易懂且便于阅读理解信息。如果只实现了其中之一,则未实现者将默认使用已实现者进行替代。如果都没有实现,则会默认使用继承自object类中相应方法。
建议至少定义一个__repr__()
方法,在大多数情况下它将足够用来输出有意义并可辨识资源信息,并作为后备方案以防未定义 __str__()
.
__add__(self, other)
: 加法运算符+
。__sub__(self, other)
: 减法运算符-
。__mul__(self, other)
: 乘法运算符*
。__truediv__(self, other)
: 真除法运算符/
.__floordiv__(self, other)
: 地板除法运算符//
.__mod__(self, other)
: 取模(余数)操作 %
.__eq__(self, other)
: 等于操作=
.__ne__(self, other)
: 不等于操作不等于操作.class TestClassMethod: value = 100 def __add__(self, other): return self.value + other def __sub__(self, other): return self.value - other def __mul__(self, other): return self.value * other def __truediv__(self, other): return self.value / other def __floordiv__(self, other): return self.value // other def __mod__(self, other): return self.value % other def __eq__(self, other): return self.value == other def __ne__(self, other): return self.value != other # 大于 def __gt__(self, other): return self.value > other # 大于等于 def __ge__(self, other): return self.value >= other # 小于 def __lt__(self, other): return self.value < other # 小于等于 def __le__(self, other): return self.value <= other method = TestClassMethod() print(method + 100) print(method - 100) print(method * 100) print(method / 100) print(method // 100) print(method % 100) print(method == 100) print(method != 100) print(method > 100) print(method >= 100) print(method < 100) print(method <= 100)
属性访问相关的特殊方法可以帮助我们自定义属性的获取、设置和删除行为:
class TestClassMethod: def __getattr__(self, name): # 当尝试获取一个不存在的属性时调用 print(f"【报错】!!尝试获取不存在的属性: {name} ") return '不存在的属性!' def __setattr__(self, name, value): # 当对属性赋值时调用 print(f"调用赋值方法 {name} {value}") # self.name = value 不能这样赋值,会导致递归调用 super().__setattr__(name, value) def __delattr__(self, name): # 当删除一个属性时调用 print(f"调用删除属性的方法 {name} ") super().__delattr__(name) method = TestClassMethod() method.value = 1 print(method.value) print(method.value2) del method.value
在Python中,类的属性可以分为两种:类属性和实例属性。
instance.attribute = value
),其实是在该实例中创建了一个同名的实例变量,并不会影响到其他实例或者是该变量在原来的那个class中。类属性是属于类本身的变量,它被所有该类的实例共享。这意味着如果你修改了一个类的类属性,这个改变会影响到所有该类的实例。
class MyClass:
class_attribute = 0
# 修改类属性将影响所有实例
MyClass.class_attribute = 1
instance1 = MyClass()
instance2 = MyClass()
print(instance1.class_attribute) # 输出: 1
print(instance2.class_attribute) # 输出: 1
实例属性是属于特定对象(即某个具体实例)的变量。每个对象都有自己独立的一套实例属性,修改一个对象的实例属性不会影响其他对象。
class MyClass: def __init__(self, value): self.instance_attribute = value # 每个对象都有自己独立的 instance_attribute 属性。 instance1 = MyClass(10) instance2 = MyClass(20) print(instance1.instance_attribute) # 输出: 10 print(instance2.instance_attribute) # 输出: 20 # 修改一个对象的 instance_attribute 不会影响另一个。 instance1.instance_attribute = 30 print(instance1.instance_attribute) # 输出: 30 print(instance2.instance_attribute) # 输出: 20
class TestClassModifyAttr: attribute = 0 def __init__(self, value): self.attribute = value @property def test_method(self): """ 当你尝试访问或者修改一个对象(即某个具体实例) 上不存在但在其对应类型定义中存在作为`@property`装饰器修饰过得方法时, Python解释器将调用相应方法来处理此次访问或者修改行为。 """ print("调用 test_method") a = TestClassModifyAttr(999) print(a.attribute) print(a.test_method) # 如果你尝试访问或者修改一个不存在于任何地方(既不是该类型定义中也不是其基类型定义中) # 且未通过`@property`装饰器修饰过得方法时, # 则解释器将调用 `__getattr__()` 或 `__setattr__()` 特殊方法来处理此次访问或者修改行为。 print(a.test_method2)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。