目录
类
一、类的概念
二、类的定义和使用
2.1 类的定义
2.2 实例化对象
三、类的属性和方法
3.1 属性
属性的类型:
补充--私有属性
属性的操作:
3.2 方法
方法的类型:
补充--私有方法
方法的操作
四、面对过程和面对对象
面对过程
面对对象编程的三大特性:封装、继承、多态
★★继承
★封装
多态
学习路线
Python基础篇1:表达式(常用数据类型及其函数介绍)_python函数和变量常用命名-CSDN博客
Python基础篇2:语句结构(选择、循环结构)-CSDN博客
Python入门1:函数-CSDN博客
Python入门2:模块和包-CSDN博客
类
一、类的概念
Python是一种面向对象的编程语言,面对对象中最核心的就是类(class)。类是一种具有相同属性和方法的对象的抽象。类可以包含多个属性和方法,这些属性和方法定义了对象的状态和行为,一旦定义了类,就可以通过创建其实例来访问其属性和方法,这种根据类来创建对象的过程称为实例化。
举个例子:鸟类,鸟类共有的属性如一对翅膀,双爪。共有的行为如飞翔,进食。这样当我们创建一个鸟类的实例对象时,就自动拥有这些属性和行为。
二、类的定义和使用
2.1 类的定义
在Python中,定义一个类使用关键字class,然后在类中定义属性(数据成员)和方法(成员函数)。类的属性可以是变量,类的方法可以是函数。通过实例化一个类,可以创建对象,并调用对象的方法和访问对象的属性。类支持封装、继承和多态等面向对象编程的核心概念,有助于提高代码的复用性和可维护性。
语法:
class 类名:
属性 变量
方法 函数
2.2 实例化对象
在完成类的定义后,实际上并不会立即创建一个实例。这就像是一份汽车蓝图。蓝图可以展示汽车的外观,但本身并不是一辆汽车。你无法直接驾驶蓝图,它只能用来指导真正汽车的建造,而且可以用它来制造多个汽车实例。那么,如何创建类的实例呢?
类的实例化:实例化对象是通过类(Class)创建具体实例(Instance)的过程。类是一个抽象的模板,而实例是根据这个模板创建的具体对象创建类的实例时,需要使用类名来调用。
需要注意的是:class语句本身并不创建该类的任何实例。所以在类定义完成以后,需要我们进行创建类的实例,即实例化该类的对象。这一点跟Java中的对象或者C++的对象很像,因为都是面向对象的语言。
# 定义一个简单的类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name} and I am {self.age} years old.")
# 创建一个实例化对象
person1 = Person("Alice", 30)
# 访问实例化对象的属性和方法
print(person1.name)
print(person1.age)
person1.greet()
三、类的属性和方法
3.1 属性
类中的所有变量称为属性。
属性的类型:
- 类属性:在类中,为全局变量,类和实例都可以访问。类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用
- 实例属性:局部变量,定义在实例方法里的,绑定实例对象的,只有实例才能直接访问。实例变量就是一个用 self 修饰的变量。【实例属性是属于类的实例对象的变量,用于存储每个实例特有的数据。在类的内部,实例属性通常通过
self.属性名
来访问和修改;在类的外部,通过实例对象名.属性名
来访问和修改。实例属性一般在__init__
方法或者类的其他方法中通过self.属性名 = 值
的形式来定义和赋值】
要获取对应的属性,可以直接使用点.
操作符
class Dog:
# 类属性(所有实例共享)
species = "Canis familiaris"
def __init__(self, name, age):
# 实例属性(每个实例独立)
self.name = name
self.age = age
dog1=Dog('小黄',3)
print(dog1.name) #访问实例属性 输出 小黄
print(dog1.species) #访问类属性 输出 Canis familiaris
print(Dog.species) #访问类属性,输出 Canis familiaris
补充--私有属性
私有属性:__private_attrs 在属性名前+两个下划线作为开头,声明该属性为私有,不能在类的外部被使用或直接访问,只能在类的内部进行访问和修改。在类内部的方法中使用时需要 self.__private_attrs,并配置相应getter和setter方法进行访问和修改。
类似其他语言的private,起到如下作用
- 控制访问:通过将属性设为私有,可以限制对其的直接访问,并通过getter和setter方法控制外部如何访问或修改数据。
- 提高安全性:防止类的外部代码意外修改或依赖于内部实现。
- 增强灵活性:私有属性可以随时改变其实现细节,而无需修改外部代码,从而提高代码的灵活性和可维护性。
私有属性是指以双下划线__
开头的属性,它在类的外部是不可访问的,只能在类的内部进行访问和修改。下面是一个关于私有属性的Python示例:
- 隐藏实现细节:某些属性涉及类的内部实现,外部不需要也不应该直接访问它们。例如,某个复杂算法的中间结果。
- 控制属性修改:通过私有属性,可以确保在修改属性时执行特定的逻辑,如数据校验或格式化处理。
- 防止冲突:在继承层次较深的类中,使用私有属性可以避免子类不经意地覆盖父类的属性。
class Person:
def __init__(self, name, age):
self.__name = name # 定义私有属性__name
self.__age = age # 定义私有属性__age
def get_name(self): # 获取私有属性的值
return self.__name
def get_age(self):
return self.__age
def set_name(self, name):# 设置私有属性的值
self.__name = name
def set_age(self, age):
self.__age = age
# 创建一个Person对象
person = Person("Alice", 30)
# 下面两行代码将会报错,因为__name是私有属性,无法直接访问
#print(person.__name)
#person.__name = "Bob"
# 可以通过类的方法来访问和修改私有属性
print(person.get_name()) # 输出:Alice
print(person.get_age()) # 输出:30
person.set_name("Bob")
person.set_age(25)
print(person.get_name()) # 输出:Bob
print(person.get_age()) # 输出:25
属性的操作:
- 添加属性
添加类属性,添加的属性是共享属性,类和实例都能访问
- 在类的定义中直接添加类属性
- 使用类方法来添加类属性
- 在类之外直接给类对象添加属性
- 使用setattr()函数来添加类属性
添加实例属性,添加的属性是私有属性,只有所添加的实例能访问
- 在初始化方法中添加:可以在类的
__init__
方法中通过self
关键字来添加实例属性。 - 直接赋值:在创建对象之后,也可以直接通过对象名来添加实例属性
- 使用
setattr
函数:可以使用内置函数setattr
为对象动态添加属性
- 修改属性
修改类属性,对实例和类都有影响
- 直接通过类名访问并赋值:可以直接通过类名访问类属性,并对其进行赋值修改操作
- 使用
setattr()
函数:setattr()
函数可以动态地为对象设置属性的值,包括类属性 - 使用
__dict__
属性:每个类都有一个__dict__
属性,它是一个字典,包含了类的命名空间中的所有属性。可以直接通过修改这个字典来修改类属性的值。
修改实例属性值,只影响所修改的实例
- 直接通过实例对象修改属性:可以通过点号(.)来直接访问和修改实例对象的属性
- 使用
setattr()
函数:setattr()
函数可以动态地为对象设置属性的值,包括实例属性 -
使用__setattr__()方法:可以在类中定义__setattr__()方法来自定义属性的设置行为。当尝试设置实例属性时会自动调用__setattr__()方法。例如:
class Person: def __init__(self, name): self.name = name def __setattr__(self, attr, value): if attr == "name": self.__dict__[attr] = value.upper() else: self.__dict__[attr] = value person = Person("Alice") person.name = "Bob" print(person.name) # 输出 "BOB"
- 直接访问实例的__dict__属性:每个实例对象都有一个__dict__属性,其中存储了实例的属性和对应的值。可以直接修改__dict__来修改实例的属性。
- 删除属性
删除类属性 对实例和类都有影响
- 使用
del
关键字:可以直接使用del
关键字来删除类属性 - 使用
delattr()
函数:可以使用内置函数delattr()
来删除类属性 -
使用
del
关键字在类内部删除属性:可以在类的方法内部使用del
关键字来删除类属性
删除实例属性 只影响所删除的实例
- 使用
del
关键字:可以直接使用del
关键字来删除实例属性 - 使用
delattr()
函数:可以使用内置函数delattr()
来删除实例属性 -
赋予
None
值:可以将实例属性赋值为None
来删除属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("Alice", 25)
print(person.name) # 输出 "Alice"
person.name = None
print(person.name) # 输出 None,表示name属性已被删除
3.2 方法
类中的所有函数通常称为方法。
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。
要使用对应的方法,可以直接使用点.
操作符
-
实例方法必须通过实例调用
-
类方法可通过类或实例调用
-
静态方法可通过类或实例调用
方法的类型:
- 类方法:
特点:类方法可以使用类属性,不能使用实例属性;类和实例都可以访问类方法
定义方式:在方法的上面添加@classmethod装饰器,方法的参数(cls),这里的cls就是代表类
class Person:
national='中国'
@classmethod
def study(cls): #类方法
print('正在学习')
- 构造方法:
特点:构造方法可以使用类属性和实例属性,它是一个特殊的方法,用于在实例化类的对象时初始化对象的属性。
语法:def __init__(self,参数1,参数2...)
作用:在Python中,构造方法是一个特殊的方法,用于在实例化一个类的对象时初始化对象的属性。构造方法在类的定义中使用__init__()
方法来实现,构造方法通常用于为类的实例设置初始值。该方法在实例化对象时会自动调用,类不可以直接调用
一般用来定义实例的属性或者需要提前准备好的数据
class Person:
national='中国'
def __init__(self, name, age): #构造方法
self.name = name
self.age = age
print("构造方法")
p1=Person('zhangsan',16)
- 实例方法
特点:实例方法可以使用类属性和实例属性。它是普通的方法,参数必须有 self
,定义格式为 def 函数名 (self, [参数])
,需要先实例化对象才能调用,类不能直接访问实例方法。
class Person:
national='中国'
def graduate(self): #实例方法
print(f'{self.name}已经毕业了')
- 静态方法
特点:它可以使用类属性,但不能使用实例属性。类和实例都可以访问静态方法
定义方式:在普通方法上添加@staticmethod装饰器,没有参数。
class Person:
national='中国'
@staticmethod
def operation(): #静态方法
print('静态方法')
补充--私有方法
私有方法:__private_method 在方法名前+两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。在类的内部使用时,通过 self.__private_method
来调用。
目的是为了隐藏类的内部实现细节,只供类本身或者其子类使用
私有属性的作用和应用场景包括:
- 封装数据:私有属性可以将对象的数据隐藏起来,只允许通过类的方法来访问和修改,从而实现数据的封装和保护。
- 防止误操作:私有属性可以避免外部直接对属性进行修改,减少代码bug的可能性,确保数据的正确性。
- 控制访问权限:私有属性可以限制对对象的访问权限,只允许通过类的接口来操作对象,提高代码的可维护性和可扩展性。
- 信息隐藏:私有属性可以隐藏对象内部的实现细节,只暴露必要的接口,降低对象之间的耦合性,提高代码的灵活性。
总结:
方法类型 | 装饰器 | 第一个参数 | 访问类属性 | 访问实例属性 | 调用方式 |
---|---|---|---|---|---|
实例方法 | 无 | self | 可以 | 可以 | 必须通过实例 |
类方法 | @classmethod | cls | 可以 | 不可以 | 类或实例 |
静态方法 | @staticmethod | 无 | 不可以 | 不可以 | 类或实例 |
构造方法 | 无(特殊方法) | self | 可以 | 可以 | 自动调用 |
方法的操作
- 添加方法
- 在类的定义中直接添加:可以在类的定义内部直接使用
def
关键字定义新的方法 - 使用类方法动态添加:可以通过修改类的
__dict__
属性或使用setattr()
函数来动态添加方法
class MyClass:
def __init__(self):
pass
def new_method(self):
print("这是通过动态添加的方法")
# 使用 setattr 动态添加方法
setattr(MyClass, 'new_method', new_method)
obj = MyClass()
obj.new_method()
- 修改方法
- 直接在类的定义中修改:如果需要修改方法的实现,可以直接在类的定义中修改方法的代码
- 动态修改方法:可以通过修改类的
__dict__
属性或使用setattr()
函数来动态修改方法
class MyClass:
def __init__(self):
pass
def old_method(self):
print("这是旧的方法")
def new_implementation(self):
print("这是新的实现")
# 使用 setattr 动态修改方法
setattr(MyClass, 'old_method', new_implementation)
obj = MyClass()
obj.old_method()
- 删除方法
- 使用
del
关键字:可以直接使用del
关键字来删除类的方法 - 使用
delattr()
函数:可以使用内置函数delattr()
来删除类的方法
class MyClass:
def __init__(self):
pass
def method_to_delete(self):
print("这是要删除的方法")
obj = MyClass()
delattr(MyClass, 'method_to_delete')
# 下面这行代码会报错,因为方法已经被删除
# obj.method_to_delete()
四、面对过程和面对对象
参照博主:
Python面向对象详解(非常详细)-CSDN博客
面向对象三大特性:封装、继承、多态(最全面最详细的解释)_封装继承多态是面向对象编程的三大特征描述正确的是-CSDN博客
面对过程
过程式编程是一种编程范式,其主要思想是按照一系列步骤或过程来执行任务。在过程式编程中,程序主要由一系列函数或过程组成,这些函数或过程按照顺序执行,并且可以共享全局数据。过程式编程强调的是按照步骤处理问题,强调程序的执行流程,是一种比较直线性的编程方式。
面对对象编程的三大特性:封装、继承、多态
面向对象编程(Object-Oriented Programming,OOP)是另一种编程范式,其主要思想是将数据和操作封装在一个对象中。在面向对象编程中,程序主要由对象组成,每个对象包含了数据和定义了可以对这些数据执行的操作(方法)。面向对象编程强调的是将问题看作对象之间的交互,从而更贴近现实世界的建模方式,提高了代码的可维护性和重用性。
总的来说,过程式编程更侧重于按照步骤执行任务,而面向对象编程更侧重于对数据和操作的封装和组织。在实际开发中,可以根据不同的需求和场景选择合适的编程范式进行开发。
★★继承
定义:继承指的是某个对象可以继承另一个对象的特性,从而快速构建具有相似属性的对象。它可以让子类继承父类的属性和方法,并且在基础上进行扩展
特点:如果父类的某个属性或方法也在子类中定义了,那么子类会重写父类的属性或方法,这样子类可以更好地针对自己的特定要求来实现相应的功能,这样可以减少重复代码,提高代码的重用性和可维护性
子类可以继承父类的属性和方法
- 单继承:class 子类(父类):
一个类可以继承另一个类的属性和方法,这就是简单的单继承
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} makes a sound")
class Dog(Animal): #单继承
def speak(self):
print(f"{self.name} barks")
dog1 = Dog("Dog")
dog1.speak() #输出Dog barks
多继承:class 子类(父类1, 父类2...)
可以继承多个父类,调用方法按顺序查找,先查询自身有无,再从左往右查询各个父类有无
class A:
def method_a(self):
print("Method A")
class B:
def method_b(self):
print("Method B")
class C(A, B):
def method_c(self):
print("Method C")
obj = C()
obj.method_a() #输出Method A
obj.method_b() #输出Method B
obj.method_c() #输出Method C
- 超类:super(类名,实例)
在Python中,父类也被称为超类(superclass),子类也称为派生类(subclass)。子类可以直接访问父类的方法和属性,并可以调用父类的构造函数来初始化父类的属性.
super() 是一个内建函数,通常用于调用父类的方法。它的作用是返回一个代理对象,通过该对象可以调用父类中的方法。使用 super() 的一个常见场景是在子类的方法中调用父类的同名方法,可以继承父类的行为并添加一些特定的功能。
class ParentClass:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Hello, my name is {self.name}")
class ChildClass(ParentClass):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def greet(self):
super().greet()
print(f"I am {self.age} years old")
childClass = ChildClass(name="John", age=20)
childClass.greet()
#输出:Hello, my name is John
# I am 20 years old
在上面的例子中,ChildClass
继承自 ParentClass
,子类重写了 greet
方法来增加年龄信息。在子类的构造函数中,使用 super().__init__(name)
调用父类的构造函数,确保父类中的初始化逻辑也被执行。在子类的 greet
方法中,通过 super().greet()
调用父类的 greet
方法,然后再添加额外的信息。
★封装
定义:封装意味着将对象的状态和行为进行封装,它将数据和方法封装在一个单独的单元中,使其对外只暴露必要的接口,从而提高了安全性和可维护性
特点:可以利用访问控制修饰符来实现封装,包括公有、私有、受保护和包访问等四种级别
上述设置私有属性和私有方法,可以完全屏蔽该属性和方法不被子类继承。但有时候我们希望属性和方法能够局部开放,某些子类也可以继承和使用相关属性方法,这时候就需要用到封装的技术,将原本的私有属性和方法名用另一种表现形式对外提供接口。
使用方式:在Python中,可以使用属性来封装类的数据。通过定义属性,可以限制对于属性的直接访问,并提供对属性的访问和修改方法。这些属性成为私有属性 ,私有属性可以通过装饰器@property
和@属性名.setter
实现封装。
可读:@property
#封装
class student:
def __init__(self,sno,sname):
self.sno=sno
self.__sname=sname
@property
def name(self):
return self.__sname
def study(self):
print(f'{self.__sname}在学校学习')
s1=student(1,'tester01')
print(s1.name)
可写:@可读属性名.setter
#封装
class student:
def __init__(self,sno,sname):
self.sno=sno
self.__sname=sname
@property
def name(self):
return self.__sname
@name.setter
def name(self,name):
self.__sname=name
def study(self):
print(f'{self.__sname}在学校学习')
s1=student(1,'tester01')
s1.name='tester02'
print(s1.name) #输出tester02
多态
定义:多态是指同一种行为在不同的对象上具有不同的表现形式,即在不同的情境下,同一个方法可以被不同的对象进行调用。它让不同类的对象对同一消息做出不同的响应
特点:多态是一种通过继承、重写和接口实现的机制;基于继承的实现,在这种实现中,父类定义一些通用的方法,子类则可以重写这些方法并实现不同的功能;基于接口的实现,在这种实现中,可以让不同的类实现同一个接口,从而实现多态
#多态
class Duck:
def fly(self):
print("Duck fly")
class Swan:
def fly(self):
print("Swan fly")
class Plane:
def fly(self):
print("Plan fly")
def fly(obj):
obj.fly()
duck = Duck()
swan = Swan()
plane = Plane()
fly(duck) #Duck fly
fly(swan) #Swan fly
fly(plane) #Plan fly