面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它将数据和操作数据的方法组合在一起,以便将数据和行为视为一个整体。这种编程范式的历程可以追溯到20世纪60年代,但直到80年代才开始流行。
在面向对象编程中,数据和方法被组织成类(Class),类是一种抽象数据类型,它定义了一组属性和方法。对象(Object)是类的一个实例1,它包含了类的属性和方法。通过创建对象,我们可以使用类中定义的方法来操作对象的属性。
类可描述事物,万物皆可是对象。对象具有具体的属性和指定的行为
对象名=类名称()
类是描述了一组有相同特性(属性)和相同行为(方法)的一组对象的集合。
对象或实体所拥有的特征在类中表示时称为类的属性。对象执行的操作称为类的方法。
class Student:
#类的属性 即:成员变量
name = None
Id = None
#类的行为 即:成员方法
def GoStudy(self)"
print(f"{self.name}study")
self作用: 在成员方法内部,要访问成员变量,必须加self,其中的self代表类的实例,而非类.
类本身包含了类的属性、方法和其他类级别的成员,它定义了一组对象共享的特征和行为
self
确实是在定义类的方法时必须有的尽管在调用时不需要显式传入相应的参数。`self`在类的方法中的作用非常重要。在参数列表中可以忽略掉
代表实例:self
是一个约定俗成的名称,它代表类的实例本身。通过self
,你可以在方法内部访问和操作该实例的属性和方法。
(1)访问成员变量:在类的方法中,如果要访问类的成员变量(也称为属性),必须使用self
来引用它们。这样Python才知道你要访问的是实例的属性而不是局部变量。
(2) [ 在类的方法中,要访问类的成员变量(也称为属性),需要使用self关键字来引用它们。 ]
区分类成员和局部变量:使用self
可以帮助区分类成员(属于类的属性和方法)和方法内部的局部变量。这有助于避免命名冲突和混淆。
class MyClass:
def __init__(self, value):
self.value = value # 使用self访问成员变量value
def print_value(self):
print(self.value) # 使用self访问成员变量value
# 创建对象并调用方法
obj = MyClass(42)
obj.print_value() # 输出: 42
总之,self
在Python中扮演着关键的角色,它允许类的方法操作类的实例并访问其属性。因此,虽然不需要在调用方法时显式传入self
参数,但在方法定义中必须有self
参数来引用实例。
2.创建对象
对象名 = 类的名称()
stu1 = Student()
在Python中,类(Class)是一种蓝图或模板,用于创建对象(Object)。类定义了对象的属性(Attributes)和行为(Methods)。让我解释一下它们之间的概念:
__init__
方法)来初始化对象的属性。示例:
class Person:
def __init__(self, name, age):
self.name = name # 属性1: 名字
self.age = age # 属性2: 年龄
# 创建一个Person对象
person1 = Person("Alice", 30)
# 访问对象的属性
print(person1.name) # 输出: Alice
print(person1.age) # 输出: 30
self
)作为第一个参数,以便在方法内部访问属性。示例:
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name} is barking!")
# 创建一个Dog对象
dog1 = Dog("Buddy")
# 调用对象的方法
dog1.bark() # 输出: Buddy is barking!
总之,属性定义了对象的特性和状态,而方法定义了对象的行为。通过使用类,你可以创建具有共同属性和行为的多个对象。
构造方法在Python中通常使用`__init__`方法来定义。
通过构造方法,你可以在创建类的实例时传递参数,并将这些参数用于初始化实例的属性。
在下面的demo中没有提前写成员变量也是可以的,因为Py中可以在构造方法(__init__方法)内部动态地创建并初始化成员变量(实例属性),而不需要提前在类定义中声明它们。
这意味着你可以在构造方法中为对象添加属性,而不必提前在类定义中列出所有可能的属性。这可以根据对象的实际需求来进行,从而使你能够更灵活地使用类。
class Person:
def __init__(self, name, age):
self.name = name # 使用传入的name参数初始化name属性
self.age = age # 使用传入的age参数初始化age属性
# 创建Person对象时传递参数
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
# 访问对象的属性
print(person1.name) # 输出: Alice
print(person1.age) # 输出: 30
print(person2.name) # 输出: Bob
print(person2.age) # 输出: 25
证明有构造方法会自动执行,也就是说明了在构造方法中的变量会被创建且被赋值。
当创建Person
对象时,必须传递这两个参数,这样对象的属性就被正确赋值。
__init__
方法接受两个参数(name
和age
),并将它们用于初始化实例的属性。
__init__
方法示例:class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("Alice", 30)
print(person.name) # 输出: Alice
print(person.age) # 输出: 30
__str__
和 __repr__
方法示例:class MyClass:
def __init__(self, value):
self.value = value
def __str__(self):
return f"MyClass instance with value: {self.value}"
def __repr__(self):
return f"MyClass({self.value})"
obj = MyClass(42)
print(str(obj)) # 输出: MyClass instance with value: 42
print(repr(obj)) # 输出: MyClass(42)
__getitem__
和 __setitem__
方法示例:class MyList:
def __init__(self):
self.data = []
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
my_list = MyList()
my_list.data = [1, 2, 3]
print(my_list[0]) # 输出: 1
my_list[1] = 42
print(my_list[1]) # 输出: 42
__len__
方法示例:class MyContainer:
def __init__(self, data):
self.data = data
def __len__(self):
return len(self.data)
container = MyContainer([1, 2, 3, 4, 5])
print(len(container)) # 输出: 5
__iter__
和 __next__
方法示例(创建一个可迭代的类):class MyRange:
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.start >= self.end:
raise StopIteration
current = self.start
self.start += 1
return current
# 使用可迭代对象
my_range = MyRange(1, 5)
for num in my_range:
print(num) # 输出: 1 2 3 4
__eq__
, __lt__
, 和 __gt__
方法示例(自定义对象的比较行为):class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __lt__(self, other):
return self.x < other.x and self.y < other.y
def __gt__(self, other):
return self.x > other.x and self.y > other.y
point1 = Point(1, 2)
point2 = Point(1, 2)
point3 = Point(2, 3)
print(point1 == point2) # 输出: True
print(point1 < point3) # 输出: True
print(point1 > point3) # 输出: False
继续探讨Python中的魔术方法的示例:
__contains__
方法示例(自定义对象的成员资格检查):class MyList:
def __init__(self, data):
self.data = data
def __contains__(self, item):
return item in self.data
my_list = MyList([1, 2, 3, 4, 5])
print(3 in my_list) # 输出: True
print(6 in my_list) # 输出: False
__add__
, __sub__
, 和 __mul__
方法示例(自定义对象的数学操作):class ComplexNumber:
def __init__(self, real, imaginary):
self.real = real
self.imaginary = imaginary
def __add__(self, other):
real_sum = self.real + other.real
imaginary_sum = self.imaginary + other.imaginary
return ComplexNumber(real_sum, imaginary_sum)
def __sub__(self, other):
real_diff = self.real - other.real
imaginary_diff = self.imaginary - other.imaginary
return ComplexNumber(real_diff, imaginary_diff)
def __mul__(self, other):
real_product = self.real * other.real - self.imaginary * other.imaginary
imaginary_product = self.real * other.imaginary + self.imaginary * other.real
return ComplexNumber(real_product, imaginary_product)
def __str__(self):
return f"{self.real} + {self.imaginary}i"
# 使用自定义复数类
c1 = ComplexNumber(1, 2)
c2 = ComplexNumber(2, 3)
c3 = c1 + c2
print(c3) # 输出: 3 + 5i
c4 = c1 - c2
print(c4) # 输出: -1 - 1i
c5 = c1 * c2
print(c5) # 输出: -4 + 7i
继续探讨Python中的魔术方法的示例:
__enter__
和 __exit__
方法示例(上下文管理器):class FileContextManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_value, traceback):
self.file.close()
# 使用上下文管理器来读取文件
with FileContextManager('example.txt', 'r') as file:
data = file.read()
print(data)
__call__
方法示例(使对象可调用):class CallableClass:
def __init__(self):
self.counter = 0
def __call__(self):
self.counter += 1
return f"Called {self.counter} times."
callable_obj = CallableClass()
print(callable_obj()) # 输出: Called 1 times.
print(callable_obj()) # 输出: Called 2 times.
__del__
方法示例(析构方法,不建议常用):class MyClass:
def __init__(self, value):
self.value = value
def __del__(self):
print(f"Deleting an instance with value: {self.value}")
obj1 = MyClass(42)
obj2 = obj1 # 创建对同一对象的引用
del obj1 # 不会触发析构方法
del obj2 # 触发析构方法,输出: Deleting an instance with value: 42
这些示例继续展示了魔术方法的使用,包括上下文管理器、使对象可调用、析构方法等。请注意,析构方法__del__
不常用,因为Python通常会自动处理垃圾回收。根据你的需求,选择实现适当的魔术方法来自定义对象的行为。
它使得类可以自由地改变内部实现,而不会对外部的代码产生负面影响。
封装是面向对象编程的三大特性之一,它指的是将数据(属性)和操作数据的方法(方法)封装在一个类内部,同时对外部隐藏类的内部实现细节。封装有以下几个关键概念:
属性私有化(Private Attributes):通常使用特殊的命名约定,如在属性名称前面添加一个下划线(例如 _value
)来表示属性是私有的,外部代码不应直接访问它们。
公有方法(Public Methods):提供公有方法来访问和操作私有属性。这些方法允许外部代码以受控的方式访问和修改对象的状态。
信息隐藏(Information Hiding):通过封装,隐藏了类的内部实现细节,使对象的使用者只需关注如何使用对象,而不需要了解其内部的工作原理。
示例:
class Student:
def __init__(self, name, age):
self._name = name # 私有属性
self._age = age # 私有属性
def get_name(self): # 公有方法访问私有属性
return self._name
def set_age(self, age): # 公有方法修改私有属性
if age > 0:
self._age = age
# 创建Student对象
student = Student("Alice", 20)
# 访问和修改属性通过公有方法
print(student.get_name()) # 输出: Alice
student.set_age(21)
print(student._age) # 输出: 21(虽然属性是私有的,但仍然可以访问)
封装的优点包括:
在Python中,私有成员通常通过命名约定来实现,而不是严格的访问控制关键字(如Java中的private
)
私有成员的方式:只需要在变量和方法,以__开头(2个下划线)
其无法被类对象使用,但可以被其他成员使用【以公共的方法调用不公共的方法】
__age=None
def __callMe(self):
#可以在私有方法内使用私有变量
def use_age_Mrthod(self):
if self.__age :
else :
self._ _callMe()
有新的内容,使用父类的成员变量和方法
class 类名(父类):
结构
继承是面向对象编程的三大特性之一,它允许一个类(子类)基于另一个类(父类)的定义来创建新的类。子类继承了父类的属性和方法,并可以在此基础上添加新的属性和方法,或者重写父类的方法。继承有以下关键概念:
父类和子类(Base Class and Derived Class):父类是被继承的类,子类是继承父类的类。
继承关系(Inheritance Relationship):子类继承了父类的属性和方法。
重写(Override):子类可以重写父类的方法,以改变或扩展方法的行为。
扩展(Extension):子类可以添加新的属性和方法。
示例:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
pass # 父类的方法,可以在子类中重写
class Dog(Animal): # Dog是Animal的子类
def speak(self): # 重写父类的方法
return f"{self.name} says Woof!"
def wag_tail(self): # 子类添加新方法
return f"{self.name} wags tail."
# 创建Dog对象
dog = Dog("Buddy")
print(dog.speak()) # 输出: Buddy says Woof!
print(dog.wag_tail()) # 输出: Buddy wags tail.
继承的优点包括:
单继承是面向对象编程中的一个概念,它指的是一个子类只能继承自一个父类的特性和行为。在单继承模型中,一个类只能有一个直接的父类,这是Python的默认继承方式。这种继承模型有以下特点:
单一的继承链:每个类只有一个直接的父类,从而构成了一条单一的继承链。这意味着子类只能继承一个父类的特性和行为。
简单明了:单继承模型相对简单,易于理解和维护。每个类只有一个父类,不会出现多重继承的复杂性。
Python的默认继承模型:Python默认采用单继承模型,这是因为它更加简单和直观,适用于大多数情况。
示例:
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
dog = Dog()
print(dog.speak()) # 输出: Woof!
cat = Cat()
print(cat.speak()) # 输出: Meow!
在上面的示例中,Dog
和 Cat
类都继承自 Animal
类,它们构成了一条单一的继承链。每个子类重写了父类的 speak
方法,以实现自己的行为。
多继承是面向对象编程中的一个概念,它指的是一个子类可以继承自多个父类的特性和行为。与单继承不同,多继承允许一个类同时具有多个直接的父类。在多继承模型中,一个子类可以继承多个不同父类的属性和方法。
多继承链:一个子类可以继承多个父类,从而构成多个继承链。这意味着子类可以具有多个不同父类的特性和行为。
复杂性:多继承模型相对复杂,因为可能会出现多个父类之间的冲突和重复。需要小心设计和解决这些问题。
Python的多继承:Python支持多继承,允许一个类继承自多个父类。在多继承情况下,类可以使用逗号分隔列表来指定多个父类。
示例:
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Bird:
def speak(self):
return "Chirp!"
# 多继承示例
class Pet(Dog, Cat, Bird):
pass
pet = Pet()
print(pet.speak()) # 输出: Woof!(优先调用第一个父类的方法)
在上面的示例中,Pet
类同时继承自 Dog
、Cat
和 Bird
三个父类,因此它可以调用这三个父类中的 speak
方法。
需要注意的是,多继承可能会引入冲突和命名空间问题,因此需要小心使用,确保合理设计类的层次结构,以避免混淆和复杂性。在Python中,可以使用super()
函数来调用多继承中的父类方法,以解决一些问题。
pass
是Python中的一个关键字,它是一个空语句,用于表示不执行任何操作。pass
主要用于语法完整性,当代码块需要存在但不需要执行任何操作时,可以使用它。在其他编程语言中,通常使用大括号 {}
来表示空代码块,但在Python中,使用 pass
来达到相同的目的。
常见用途包括:
pass
作为占位符,以后再添加实际的代码。def my_function():
pass # 占位符,未实现功能
pass
表示循环体为空。for item in my_list:
pass # 暂时没有操作
pass
。class MyClass:
pass # 暂时没有属性或方法
pass
的存在允许你在代码中留下一些空白的地方,而不会引发语法错误。但要注意,过多地使用 pass
可能会导致代码的可读性下降,因此应该谨慎使用,确保它们的存在是合理的。
(1)子类重写父类的方法
class Person:
name = "Jack"
def call_Name(self):
print(f"{self.name}hhh")
class Student(Person):
name = "Peter"
def call_Name(self):
print(f"{self.name}")
stu = Person()
print(stu.name)
stu.call_Name()
stu = Student()
print(stu.name)
stu.call_Name()
方式一:调用父类的方法
成员变量:父类名称.成员变量
成员方法:父类名称.成员方法(self)
# 调用父类的成员
class Parent:
def __init__(self):
self.value = 42
def parent_method(self):
return "Hello from Parent!"
class Child(Parent):
def child_method(self):
parent_value = Parent().value # 调用父类的属性
parent_greeting = Parent().parent_method() # 调用父类的方法
return f"Child says: Parent value is {parent_value}, {parent_greeting}"
child = Child()
print(child.child_method())
方法二 使用super()调用父类成员
成员变量:super().成员变量
成员方法:super().成员方法()
super() 并不直接支持访问父类的属性。你需要通过父类的构造函数 super().init() 来初始化属性,然后才能在子类中访问它们。
# 使用super()调用父类的成员
class Parent:
def __init__(self):
self.value = 42
def parent_method(self):
return "Hello from Parent!"
class Child(Parent):
def child_method(self):
parent_value = super().value # 使用super()调用父类的属性
parent_greeting = super().parent_method() # 使用super()调用父类的方法
return f"Child says: Parent value is {parent_value}, {parent_greeting}"
child = Child()
print(child.child_method())
变量注释
形参列表的注释
类型注解是Python 3引入的一项功能,它允许你在变量、函数参数和函数返回值等地方添加类型信息,以提供代码的可读性和类型检查。虽然类型注解在运行时不会影响程序的行为,但它可以用于静态类型检查工具,如mypy,以帮助捕获潜在的类型错误。
做一个备注
#可以不需要
name: str = "John" # 声明name变量的类型为str
age: int = 30 # 声明age变量的类型为int
# 在无法看出类型时使用
varx:int =random.randint(1,10) # type: int
函数->返回值类型
def greet(name: str) -> str:
return f"Hello, {name}"
def add(a: int, b: int) -> int:
return a + b
在上述示例中,函数greet
接受一个参数name
,其类型为str
,并且返回一个str
类型的值。函数add
接受两个参数a
和b
,都是int
类型,并返回一个int
类型的值。
from typing import List
def calculate_average(numbers: List[float]) -> float:
total = sum(numbers)
return total / len(numbers)
在上述示例中,我们使用了List[float]
来注解参数numbers
,表示这是一个浮点数的列表,函数返回值也被注解为float
类型。
类型注解有助于提高代码的可读性,尤其对于大型项目和团队合作而言,它们可以更清晰地传达变量和函数的预期类型。此外,类型检查工具如mypy可以根据这些注解来检查代码中的类型错误,帮助提前发现潜在的问题。
(1)基础容器
my_list:list=[1,2,3]
my_tuple:tuple=("hello",False,123)
my_set:set={1,2,3}
my_dict:dict ={"hrllo",123}
print(my_list)
print(my_tuple)
print(my_set)
print(my_dict)
(2)详细容器
元组的详细类型设置要详细,每一个都要标记
字典的详细类型要详细。键值都要
my_list:list[int]=[1,2,3]
my_tuple:tuple[str, bool, int]=("hello",False,123)
my_set:set[int]={1,2,3}
my_dict:dict[str,int] ={"hrllo",123}
print(my_list)
print(my_tuple)
print(my_set)
print(my_dict)
导包:from typing import Union
使用:Union[类型,类型,…,类型]
Union类型是Python类型注解中的一种,它允许变量或函数参数可以具有多种不同类型中的一个。Union类型用于描述一个变量可以接受多个可能的数据类型,提供了更灵活的类型注解方式。
变量的:
from typing import Union
# 声明变量的Union类型
variable: Union[int, float, str]
# 变量可以是int、float或str中的任意一个
variable = 42 # 合法,变量是整数类型
variable = 3.14 # 合法,变量是浮点数类型
variable = "Hello" # 合法,变量是字符串类型
# 但不合法的情况,会引发类型错误
variable = [1, 2, 3] # 不合法,列表不在Union类型中的选项中
函数的
from typing import Union
def double_or_square(value: Union[int, float]) -> Union[int, float]:
if isinstance(value, int):
return value * 2
elif isinstance(value, float):
return value ** 2
result1 = double_or_square(5) # 返回整数 10
result2 = double_or_square(3.5) # 返回浮点数 12.25
在上面的示例中,double_or_square
函数接受一个参数value
,它的类型注解使用了Union类型,表示可以是int
或float
中的任意一种类型。函数根据参数的类型执行不同的操作,然后返回相应的类型。
多种状态,处于某种身份,表现出不同的对象会得到不同的状态
多态是面向对象编程的三大特性之一,它允许不同的对象对相同的方法名产生不同的行为。多态使得代码更加灵活,能够处理不同类型的对象,而无需关心其具体类型。多态有以下关键概念:
基类和派生类(Base Class and Derived Class):基类定义了通用的接口和方法,派生类继承了基类,并可以根据需要重写方法。
方法重写(Method Overriding):派生类可以重写基类中已有的方法,以实现自己的行为。
多态性(Polymorphism):不同的对象可以使用相同的方法名,但产生不同的行为。
示例:
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
# 多态性示例
animals = [Dog(), Cat()]
for animal in animals:
print(animal.speak())
# 输出:
# Woof!
# Meow!
多态的优点包括:
父类用来指定方法是什么,子类来决定具体的实现过程。
抽象类:
在Python中,你可以使用abc
模块创建抽象类。以下是一个抽象类的示例:
from abc import ABC, abstractmethod
class Animal(ABC): # 继承ABC类表示抽象类
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
dog = Dog()
cat = Cat()
print(dog.speak()) # 输出: Woof!
print(cat.speak()) # 输出: Meow!