目录
面向对象编程
面向对象编程,在英文中称之为Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。Python是一个纯天然面向对象的编程语言,在Python中所有数据类型都可以视为对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

类与对象基本概念
| 类(Class) | 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例 |
| 方法 | 类中定义的函数 |
| 类变量 | 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用 |
| 数据成员 | 类变量或者实例变量用于处理类及其实例对象的相关的数据 |
| 方法重写 | 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写 |
| 局部变量 | 定义在方法中的变量,只作用于当前实例的类 |
| 实例变量 | 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量 |
| 继承 | 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal) |
| 实例化 | 创建一个类的实例,类的具体对象,通过类创建对象的过程称为实例化。 |
| 对象 | 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法 |
类是对象的蓝图和模板,而对象是类的实例。类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。
把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装隐藏内部细节,通过继承实现类的特化(specialization)和泛化(generalization),通过多态实现基于对象类型的动态分派。
class Student():
def __init__(self,name,age): #构造方法/构造函数),该方法在类实例化时会自动调用
self.__name=name
self.age=age
'''类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,
按照惯例它的名称是 self
self代表类的实例,而非类
'''
def talk(self):
print('%s is %d years old' %(self.__name,self.age))
#私有属性在类内部被重命名以实现私有化,访问时需要通过特定的方法(如getter和setter
def set_name(self,name):
self.__name=name
s=Student('liu',10)
s.talk() #liu is 10 years old
s.__name='li' #python3 私有属性或方法是不能被子类直接访问的。如果尝试修改私有属性,
#不会产生语法错误,但修改不会生效
s.age=14
s.talk() #liu is 14 years old
s.set_name('li')
s.talk() #li is 14 years old
举例
1、实现一个简单的队列类
class Queue:
def __init__(self):
self.item=[]
def enqueue(self,item):
self.item.append(item)
def dequeue(self):
return self.item.pop(0) if not self.is_empty() else None
#改为 self.items.pop() 可以模拟栈的操做了
def is_empty(self):
return len(self.item)==0
def size(self):
return len(self.item)
2、实现一个二叉树
class TreeNode:
def __init__(self,val):
self.val=val
self.left=None
self.right=None
class BinaryTree:
def __init__(self):
self.root=None
def insert(self,val):
if not self.root:
self.root=TreeNode(val)
else:
self._insert_recursively(self.root, val)
def _insert_recursively(self,node,val):
if val<node.val:
if node.left is None:
node.left=TreeNode(val)
else:
self._insert_recursively(node.left,val)
else:
if node.right is None:
node.right=TreeNode(val)
else:
self._insert_recursively(node.right,val)
3、一个简单的链表
class Node:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, value):
new_node = Node(value)
if not self.head:
self.head = new_node
else:
current = self.head
while current.next:
current = current.next
current.next = new_node
def display(self):
current = self.head
while current:
print(current.value, end=' ')
current = current.next
4、小堆类
class MinHeap:
def __init__(self):
self.heap = []
def insert(self, val):
self.heap.append(val)
self._heapify_up(len(self.heap) - 1)
def _heapify_up(self, index):
parent_index = (index - 1) // 2
if index > 0 and self.heap[index] < self.heap[parent_index]:
self.heap[index], self.heap[parent_index] = self.heap[parent_index], self.heap[index]
self._heapify_up(parent_index)
def extract_min(self):
if not self.heap:
return None
if len(self.heap) == 1:
return self.heap.pop()
root = self.heap[0]
self.heap[0] = self.heap.pop()
self._heapify_down(0)
return root
def _heapify_down(self, index):
smallest = index
left_child = 2 * index + 1
right_child = 2 * index + 2
if left_child < len(self.heap) and self.heap[left_child] < self.heap[smallest]:
smallest = left_child
if right_child < len(self.heap) and self.heap[right_child] < self.heap[smallest]:
smallest = right_child
if smallest != index:
self.heap[index], self.heap[smallest] = self.heap[smallest], self.heap[index]
self._heapify_down(smallest)
面向对象三大特性
面向对象有三大支柱:封装、继承和多态。
封装: "隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口"。在类中定义的方法其实就是把数据和对数据的操作封装起来了,在创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说只需要知道方法的名字和传入的参数,而不需要知道方法内部的实现细节。
继承:可以实现现有类的所有功能,并无需要重新编写原来的类情况下对这些功能进行扩展
多态:子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写可以让父类的同一个行为在子类中拥有不同的实现版本,当调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态。
封装
class Student:
def __init__(self, n):
self.__name = n
'''在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私
有的,在给属性命名时可以用两个下划线作为开头
'''
def __show(self):
print(self.__name)
print('__show')
def main():
stu = Student('hello')
# AttributeError: 'Student' object has no attribute '__show'
#stu.__show()
# AttributeError: 'Student' object has no attribute '__foo'
#print(stu.__name)
#Python并没有从语法上严格保证私有属性或方法的私密性,它
# 只是给私有的属性和方法换了一个名字来妨碍对它们的访问,下面就是
stu._Student__show()
print(stu._Student__name)
stu.age=10 #实例绑定任何属性和方法,这就是动态语言的灵活性
print(stu.age)
#stu1=Student('world') #AttributeError: 'Student' object has no attribute 'age'
#print(stu1.age) #给一个实例绑定的方法,对另一个实例是不起作用的
Student.age=10 #给class绑定属性或方法后,所有实例均可调用:
# __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称,在类定义里写上
stu1=Student('world')
print(stu1.age)
if __name__ == "__main__":
main()
| 访问类型 | 命名规范 | 访问限制机制 | 备注 |
|---|---|---|---|
| 公有 | var | 无限制 | 任何地方都可访问 |
| 受保护 | _var | 约定不访问,无强制限制 | 子类可访问,外部不建议访问 |
| 私有 | __var | 名称重整,防止直接访问 | 主要避免子类覆盖和外部访问 |
| 魔法方法/变量 | __var__ | 无限制 | Python内部调用接口 |
class Test:
def __init__(self):
self.public = "public"
self._protected = "protected"
self.__private = "private"
t = Test()
print(t.public) # public
print(t._protected) # protected,能访问但不建议
# print(t.__private) # 报错,AttributeError
print(t._Test__private) # private,通过名称重整访问
实例属性与类属性
| 方面 | 实例属性 | 类属性 |
|---|---|---|
| 绑定对象 | 绑定到实例 | 绑定到类 |
| 存储位置 | 实例的__dict__ | 类的__dict__ |
| 访问顺序 | 先查实例属性,再查类属性 | 直接查类属性 |
| 修改影响 | 只影响当前实例 | 影响所有未覆盖该属性的实例 |
| 定义位置 | 通常在__init__方法中定义 | 类体中定义 |
| 典型用途 | 存储实例特有数据 | 存储共享数据或常量 |
class Employee:
# 类属性,所有员工共享的公司名称和员工总数
company_name = "TechCorp"
employee_count = 0
def __init__(self, name, salary):
# 实例属性,每个员工独有的姓名和薪资
self.name = name
self.salary = salary
# 每创建一个实例,员工总数增加
Employee.employee_count += 1
def give_raise(self, amount):
# 给当前员工加薪(修改实例属性)
self.salary += amount
@classmethod
def change_company_name(cls, new_name):
# 修改类属性,改变公司名称
cls.company_name = new_name
def show_info(self):
# 显示员工信息,包括访问类属性和实例属性
print(f"员工姓名: {self.name}")
print(f"薪资: {self.salary}")
print(f"公司名称: {self.company_name}")
# 创建两个员工实例
emp1 = Employee("Alice", 7000)
emp2 = Employee("Bob", 8000)
# 访问类属性和实例属性
print(f"公司名称(通过类访问): {Employee.company_name}")
print(f"员工总数(通过类访问): {Employee.employee_count}")
print("--- emp1 信息 ---")
emp1.show_info()
print("--- emp2 信息 ---")
emp2.show_info()
# 修改emp1的实例属性salary
emp1.give_raise(1000)
print("--- emp1 加薪后 ---")
emp1.show_info()
# 修改类属性company_name,通过类方法
Employee.change_company_name("InnovateTech")
print("--- 修改公司名称后 ---")
emp1.show_info()
emp2.show_info()
# 通过实例修改类属性(注意:这会创建实例属性,覆盖类属性)
emp2.company_name = "FakeCorp"
print("--- emp2 修改公司名称为 FakeCorp ---")
print(f"emp2.company_name: {emp2.company_name}") # 实例属性
print(f"emp1.company_name: {emp1.company_name}") # 仍然是类属性
print(f"Employee.company_name: {Employee.company_name}") # 类属性
# 查看实例和类的__dict__
print("--- 查看 __dict__ ---")
print(f"Employee.__dict__['company_name']: {Employee.__dict__['company_name']}")
print(f"emp1.__dict__: {emp1.__dict__}")
print(f"emp2.__dict__: {emp2.__dict__}")
继承与多态
定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class),Python 同样支持类的继承。派生类的定义如下class son (base):子类(派生类/son)会继承父类(基类/base)的属性和方法。
class base:
#基本属性
name=''
__age = 0 #定义私有属性,私有属性在类外部无法直接进行访问
def __init__(self,n,a): #构造函数
self.name=n
self.__age=a
def talk(self):
print('call base %s is %d years old'%(self.name,self.__age))
class Son(base):
pass
s=Son('liu',10) #子类继承了父类的属性和方法
s.talk() #call base liu is 10 years old
class Son_test(base):
address=''
def __init__(self, n, a,add):
super().__init__(n, a)
self.address=add
def talk(self): #覆写父类的方法
print('son func live in%s'%(self.address))
st=Son_test('zhang',12,'beijing')
st.talk() #son func live inbeijing
b=base('sun',12)
b.talk() #call base sun is 12 years old
def base_talk(base):
"""接受所有base类的子类实例,并调用它们的talk方法
传入的任意类型,只要是base类或者子类,就会自动调用实际类型的talk()方法,这就是多态"""
base.talk()
base_talk(st) #son func live inbeijing
base_talk(s) #多态需要实现函数覆盖 call base liu is 10 years old
object与type
object是Python中所有类的最终基类(根类)。所有类(无论是内置类型还是用户自定义类)都直接或间接继承自object。它定义了所有对象共有的基础行为和接口。
object提供默认的魔法方法实现,如__str__、__repr__、__eq__等。使得Python的类体系形成统一的继承结构。作为所有对象的共同父类,方便类型检查和多态设计。
type是Python中所有类的类型,即所有类都是type的实例。type本身是一个类,同时也是一个元类(metaclass)。通过type可以动态创建类。
type负责创建类对象。作为元类,控制类的创建过程。可以用type动态生成类。
class A:
pass
print(type(A)) # <class 'type'>,A是type的实例
print(type(42)) # <class 'int'>,int是type的实例
# 动态创建类
B = type('B', (object,), {'x': 5})
b = B()
print(b.x) # 5
print(isinstance(object, type)) # True,object是type的实例
print(isinstance(type, type)) # True,type是type的实例(元类自指)
print(issubclass(object, object)) # True
print(issubclass(type, object)) # True,type是object的子类
print(issubclass(object, type)) # False
元类
元类是用来创建类的“类”,即类的类型。在Python中,类也是对象,而元类就是创建这些类对象的“工厂”。默认情况下,Python中所有类的元类都是type。通过自定义元类,可以控制类的创建过程,动态修改类的属性和方法。
元类的作用:控制类的创建:可以在类创建时自动修改类的属性、方法。实现单例模式、接口检查、自动注册等高级功能。动态创建类,比如根据配置动态生成类。框架设计中常用,如Django ORM、SQLAlchemy等大量使用元类实现自动映射和注册。
当定义一个类时:Python执行的步骤:1)收集类体中的属性和方法,形成一个字典(namespace)2)调用元类的__new__方法,创建类对象。调用元类的__init__方法,初始化类对象。3)返回类对象
| 方面 | 说明 |
|---|---|
| 元类定义 | 继承自type,重写__new__和__init__ |
| 作用 | 控制类的创建过程,动态修改类属性和方法 |
| 默认元类 | Python中默认元类是type |
| 常见应用 | 自动注册、接口检查、单例模式、动态创建类 |
| 元类与实例化 | 元类的__call__控制类实例的创建 |
鸭子类型
python中的鸭子类型是一种动态类型的概念,其核心思想源自于一句格言:“如果它走起路来像鸭子、叫起来也像鸭子,那么它就是鸭子”。这意味着在Python中,一个对象的有效性不是由其类型决定的,而是由其行为决定的。这种类型检查方式强调对象的行为比其具体类型更重要。
class Duck:
def quack(self):
print('quack')
class Person:
def quack(self):
print('I am quack like a duck')
def func_quac(duck_lick): #函数可以处理任何 具用quack方法 的对象
'''
静态类型检查发生在编译期,要求对象必须是某个特定类型的子类,鸭子类型中不需要预
定义类型发生在运行时,类型约束由对象的行为决定,而不是继承的类
'''
duck_lick.quack()
d=Duck()
p=Person()
func_quac(d) #quack
func_quac(p) #I am quack like a duck
多继承
多重继承(多继承)是面向对象编程的一个特性,允许一个子类同时继承多个父类。多重继承在设计中有其用途,但也可能导致复杂性增加,特别是当子类从多个父类中继承相同名称的方法时。多态中方法调用顺序可能受到 __mro__ 方法的影响,它展示了方法解析顺序(Method Resolution Order, MRO)。
class A:
def __init__(self,n):
self._name=n
def hello(self):
print('Hello from A')
def show_A(self):
print('call A func')
class B:
def __init__(self,n):
self._name=n
def hello(self):
print('Hello from B')
def show_B(self):
print('call B func')
class C(A, B):
def __init__(self, n):
super().__init__(n)
def hello(self):
print('Hello from C')
def show_C(self):
print('call C func')
class D(B, A):
pass
# 使用C和D来演示多重继承
c = C('li')
c.hello() # 输出: Hello from C c可掉c.show_A() c.show_B() c.show_C()
d = D('li')
d.hello() # 输出: Hello from B(因为B在继承链中先于A) d.show_B() d.show_A()
print(C.mro())
# 输出: [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
其他
__slots__
__slots__是Python类中的一个特殊变量,用于显式声明类实例允许拥有的属性集合。使用__slots__后,Python不会为实例创建默认的__dict__字典来存储属性,而是为声明的属性分配固定的空间。这样可以节省内存,提高属性访问速度,同时限制实例不能动态添加未声明的属性。
优势:节省内存
-
默认情况下,Python的实例通过
使用__dict__存储属性,__dict__是一个字典,存储属性名和属性值的映射,比较灵活但占用内存较多。__slots__后,实例不再有__dict__,属性直接存储在固定的槽(slot)中,内存占用更小。对于大量实例的类,内存节省非常明显。 -
限制属性:通过
__slots__声明的属性名限制了实例只能拥有这些属性,不能动态添加其他属性,避免误用和错误。 -
提高访问速度:由于属性存储在固定槽中,访问速度比字典查找快。
class Person:
__slots__ = ['name', 'age'] # 只允许实例拥有name和age属性
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Alice', 30)
print(p.name) # Alice
p.age = 31 # 修改允许的属性,正常
print(p.age) # 31
p.gender = 'Female' # 报错:AttributeError: 'Person' object has no attribute 'gender'
类装饰器:
1、函数装饰器(类的普通函数)2、类作为装饰器、类装饰器装饰类
| 装饰器 | 作用 | 所在模块 |
|---|---|---|
@property | 定义属性访问方法 | 内置 |
@classmethod | 定义类方法 | 内置 |
@staticmethod | 定义静态方法 | 内置 |
@functools.lru_cache | 函数结果缓存 | functools |
@dataclasses.dataclass | 自动生成类特殊方法 | dataclasses |
@contextlib.contextmanager | 创建上下文管理器 | contextlib |
@property装饰器
Python中属性和方法访问权限的问题中,虽然python不能完全‘私有’ ,但是如果直接将属性暴露给外界也是有问题的,比如没有办法检查赋给属性的值是否有效。建议将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作,Python内置的@property装饰器就是负责把一个方法变成属性调用的。
class Person():
def __init__(self, age):
self._age = age
# 访问器 - getter方法
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
def talk(self):
if self._age <= 16:
print('%d太小 不跟你玩了.' % self.age)
else:
print('%d 成年了, hi.' % self.age)
def main():
person = Person( 12)
person.talk()
person.age = 22
person.talk()
#person.name = 'liu' # AttributeError: can't set attribute
if __name__ == '__main__':
main()
装饰器实际上是利用高阶函数的特性来实现的一种便捷的语法形式(高阶函数是指接受一个或多个函数作为参数,或者返回一个函数的函数)
静态方法和类方法
前面例子中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上写在类中的方法并不需要都是对象方法。
静态方法:是一种不会自动接收类(cls)或实例(self)作为第一个参数的方法。它可以通过类直接调用,而不需要类的实例。静态方法通常用于实现与当前类的对象状态无关的功能,或者提供一些通用的工具函数。
class Car:
@staticmethod #静态方法通过装饰器@staticmethod定义,不接受类或实例作为第一个参数
def create_car(car_type):
if car_type == 'sedan':
return Sedan('sedan 时速 ')
elif car_type == 'suv':
return SUV('suv时速')
class Sedan:
def __init__(self, type):
# ... Sedan特有的属性和方法
self._type=type
def run(self):
print(self._type, "99km/h")
class SUV:
def __init__(self, t):
# ... SUV特有的属性和方法
self._type=t
def run(self):
print(self._type,"129km/h")
Car.create_car('suv').run()
Car.create_car('sedan').run()
类方法:类方法的定义是在类的定义内部使用@classmethod装饰器的函数。类方法的第一个参数是类本身作为一个实例,通常用cls作为参数名。
class MyClass:
def __init__(self, value):
self.value = value
@classmethod
def create(cls, value):
return cls(value)
# 使用定义的工厂方法创建类的实例
instance1 = MyClass.create(10)
instance2 = MyClass.create(20)
print(instance1.value) # 输出: 10
print(instance2.value) # 输出: 20
| 方法类型 | 装饰器 | 第一个参数 | 调用方式 | 访问权限 |
|---|---|---|---|---|
| 实例方法 | 无 | self | obj.method() | 可访问实例和类属性 |
| 类方法 | @classmethod | cls | Class.method() | 只能访问类属性 |
| 静态方法 | @staticmethod | 无 | Class.method() | 不能访问实例或类属性 |
class Book:
# 类变量,用于跟踪所有图书的数量
total_books = 0
def __init__(self, title, author):
self.title = title # 实例变量:书名
self.author = author # 实例变量:作者
Book.total_books += 1 # 每创建一本书,数量加一
def display_info(self):
"""实例方法:显示书籍信息"""
return f"Title: {self.title}, Author: {self.author}"
@classmethod
def get_total_books(cls):
"""类方法:获取总书籍数量"""
return cls.total_books
@staticmethod
def is_valid_title(title):
"""静态方法:检查书名是否有效"""
return isinstance(title, str) and len(title) > 0
# 创建图书实例
book1 = Book("1984", "George Orwell")
book2 = Book("To Kill a Mockingbird", "Harper Lee")
# 调用实例方法
print(book1.display_info()) # 输出: Title: 1984, Author: George Orwell
print(book2.display_info()) # 输出: Title: To Kill a Mockingbird, Author: Harper Lee
# 调用类方法
print(f"Total books: {Book.get_total_books()}") # 输出: Total books: 2
# 调用静态方法
print(Book.is_valid_title("The Great Gatsby")) # 输出: True
print(Book.is_valid_title("")) # 输出: False
类方法的特有优势
1、访问类属性第一个参数是cls,代表类本身,使得类方法可以访问和修改类的属性,并不需要创建实例。可以通过类名实例调用(推荐类名。
2、类方法常用于实现工厂方法,根据不同的参数创建类的实例
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
@classmethod
def from_string(cls, book_string):
title, author = book_string.split(", ")
return cls(title, author)
# 使用类方法创建实例
book = Book.from_string("1984, George Orwell")
print(book.title) # 输出: 1984
3、继承和多态的支持,类方法可以继承和重写,子类调用类方法cls指向子类,那么继承关系里就表现出多态性
class Animal:
@classmethod
def sound(cls):
return "Some sound"
class Dog(Animal):
@classmethod
def sound(cls):
return "Bark"
# 调用类方法
print(Animal.sound()) # 输出: Some sound
print(Dog.sound()) # 输出: Bark
静态方法的核心价值
1、不依赖于类或者实例的状态,静态方法不需要访问类或实例的属性,因此它们可以独立于类的状态进行操作。这使得静态方法适用于那些不需要访问类或实例数据的功能,增强了代码的模块化和可重用性。类和对象都可访问推荐类访问
2、组织相关功能:静态方法可以将相关的功能组织在类中,使得代码结构更加清晰。即使这些功能不需要访问类或实例的状态,将它们放在类中可以提高代码的逻辑性。
class StringUtils:
@staticmethod
def is_palindrome(s):
return s == s[::-1]
# 调用静态方法
print(StringUtils.is_palindrome("radar")) # 输出: True
3、便于命名空间管理;使用静态方法可以将相关功能封装在类中,从而避免全局命名空间的污染。这有助于管理大型项目中的命名冲突,保持代码的整洁性。
4、适用于工具类;静态方法非常适合用于工具类(Utility Classes),这些类通常只包含一些与类本身无关的辅助功能。通过静态方法,可以方便地调用这些功能,而不需要创建类的实例。
class FileUtils:
@staticmethod
def read_file(file_path):
with open(file_path, 'r') as file:
return file.read()
# 调用静态方法
content = FileUtils.read_file("example.txt")
print(content)
类方法最佳场景:1)工厂模式:创建不同配置的实例;2)单例模式:控制实例创建过程;3)资源管理:数据库连接池等;4)策略模式:通过子类改变行为;
静态方法最佳场景:1)纯工具函数:数学计算/格式转换;2)常量分组:相关常量的容器;3)算法实现:与类相关但不需要状态;4)接口实现:必须存在于类中的方法;
性能考量
调用开销:实例方法:需要创建实例(开销最大);类方法:直接通过类调用(中等);静态方法:等同于模块函数(最快)
属性查看
|
| 列出对象的所有属性和方法(包括继承的) |
obj.__dict__ | 返回对象的实例属性字典(不包括类属性) |
vars(obj) | 等同于 |
getattr(obj, 'attr', default) | 获取属性值。 |
hasattr(obj, 'attr') | 判断是否有该属性 |
setattr(obj, 'attr', value) | 设置属性值。 |
delattr(obj, 'attr') | 删除属性。 |
7999

被折叠的 条评论
为什么被折叠?



