目录
1、面向对象的三大特征
1. 封装(Encapsulation):
2. 继承(Inheritance):
3. 多态(Polymorphism):
2、类的组成
成分介绍:
1.类属性(Class Attributes):
2. 实例属性(Instance Attributes):
3. 实例方法(Instance Methods):
4. 静态方法(Static Methods):
5. 类方法(Class Methods):
一些例子有助于理解:
1. 类属性(Class Attributes):
2. 实例属性(Instance Attributes):
3. 实例方法(Instance Methods):
4. 静态方法(Static Methods):
5. 类方法(Class Methods):
6.包含这五个成分的例子:
一个简化的银行账户系统
一个简单的学生管理系统
3、动态绑定对象和方法
动态绑定属性:
动态绑定方法:
4、权限控制
1. 公共修饰符(Public):
2. 保护修饰符(Protected):
3. 私有修饰符(Private):
解释一下子类:
5、属性的设置
@property 装饰器:
@property_name.setter 装饰器:
封装是将数据(属性)和操作数据的方法(方法)捆绑在一起的概念。通过封装,对象的内部细节被隐藏,只有对外提供的接口是可见的。这有助于保护对象的状态,使得对象的使用者只需关注对象的公共接口而不必关心其内部实现。
实现封装的方式: 封装可以通过使用类、访问修饰符(如私有、保护、公共)来实现。
优势: 提高代码的模块化程度,降低了代码的耦合度,提高了代码的可维护性和可重用性。
继承是指一个类可以基于另一个类来定义,新类可以继承并重用旧类的属性和方法。被继承的类称为父类(基类、超类),继承的类称为子类(派生类)。
实现继承的方式: 子类可以通过继承父类的方式获得父类的属性和方法。这有助于代码的重用,并支持层次结构的建立。
优势: 提高了代码的可重用性,减少了代码的冗余,使得代码更加灵活和易于扩展。
多态是指同一个接口(方法或属性)可以在不同的对象上有不同的实现。在多态中,同一方法名可以被用于不同的类,这样可以通过相同的接口处理不同类型的对象。
实现多态的方式: 多态可以通过方法的重写(覆盖)和方法的重载来实现。在重写中,子类可以提供对父类方法的不同实现;在重载中,同一类中可以有多个同名方法,但参数类型或数量不同。
优势: 提高了代码的灵活性,可以使用相同的接口处理不同类型的对象,使得代码更加通用和易于维护。
这三大特征共同构成了面向对象编程的基础,通过它们,可以更好地组织和管理代码,提高代码的可读性、可维护性和可扩展性。
面向对象编程(Object-Oriented Programming,简称OOP)具有三大主要特征,它们是封装、继承和多态。下面对这三大特征进行详细解释:
在Python中,类由类属性(Class Attributes)、实例属性(Instance Attributes)、实例方法(Instance Methods)、静态方法(Static Methods)和类方法(Class Methods)等组成。以下是
作用: 类属性是与整个类关联的属性,它对于该类的所有实例都是共享的。通常用于存储类级别的信息或配置。
使用: 通过类名直接访问,也可以通过实例访问。通常在类的定义中进行声明和初始化。
class MyClass:
class_attribute = 42
# 访问类属性
print(MyClass.class_attribute)
# 也可以通过实例访问
obj = MyClass()
print(obj.class_attribute)
作用: 实例属性是属于类的特定实例的属性,每个实例都有自己的一份。用于存储对象的状态信息。
使用: 在 __init__
方法中声明和初始化。通过实例访问。
class MyClass:
def __init__(self, initial_value):
self.instance_attribute = initial_value
# 创建实例并访问实例属性
obj = MyClass(10)
print(obj.instance_attribute)
作用: 实例方法是操作实例属性的函数,可以访问并修改实例的状态。
使用: 在类中定义,第一个参数通常是 self
,表示对实例的引用,这个参数不需要操作。
class MyClass:
def instance_method(self):
print("This is an instance method.")
# 创建实例并调用实例方法
obj = MyClass()
obj.instance_method()
作用: 静态方法是与类关联但与特定实例无关的方法,通常用于执行不需要访问实例属性的操作。
使用: 使用 @staticmethod
装饰器来声明静态方法。
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
# 调用静态方法
MyClass.static_method()
作用: 类方法是与类关联的方法,它可以访问并操作类级别的属性。
使用: 使用 @classmethod
装饰器来声明类方法,第一个参数通常是 cls
,表示对类的引用。
class MyClass:
class_variable = 42
@classmethod
def class_method(cls):
print(f"This is a class method. Class variable: {cls.class_variable}")
# 调用类方法
MyClass.class_method()
这些成分的选择取决于你的设计需求。类属性用于存储整个类的信息,实例属性用于存储实例的状态,实例方法用于操作实例,静态方法和类方法用于执行不同层次的操作而不依赖于实例的状态。
配置信息: 类属性经常用于存储配置信息,例如数据库连接字符串、API密钥等。这样,所有实例都可以共享相同的配置。
class Config:
database_url = "mysql://user:password@localhost/db"
# 在应用中使用配置
print(Config.database_url)
计数器: 类属性可以用于创建计数器,跟踪类的实例创建了多少个。
class MyClass:
instance_count = 0
def __init__(self):
MyClass.instance_count += 1
# 测试计数器
obj1 = MyClass()
obj2 = MyClass()
print(MyClass.instance_count) # 输出 2
对象状态: 实例属性用于存储对象的状态信息。例如,一个 Person
类可以有实例属性 name
和 age
用于表示一个人的姓名和年龄。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# 创建 Person 对象
person = Person("John", 25)
print(person.name, person.age)
配置参数: 实例属性可以用于存储对象的配置参数,这些参数在对象创建时传递。
class Car:
def __init__(self, model, color):
self.model = model
self.color = color
# 创建 Car 对象
my_car = Car(model="Tesla", color="Red")
print(my_car.model, my_car.color)
操作对象状态: 实例方法通常用于操作对象的状态,可以访问和修改实例属性。
class BankAccount:
def __init__(self, balance):
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
else:
print("Insufficient funds")
# 使用实例方法进行账户操作
account = BankAccount(balance=1000)
account.deposit(500)
account.withdraw(200)
实例方法用于封装与对象相关的逻辑,使得代码更加模块化和易于维护。
独立功能: 静态方法用于执行与类和实例无关的独立功能。例如,一个数学工具类可以包含静态方法计算数学函数。
class MathUtils:
@staticmethod
def square(x):
return x ** 2
# 使用静态方法
result = MathUtils.square(5)
静态方法通常执行不依赖于类实例状态的操作。
访问类属性: 类方法通常用于访问和修改类属性,执行与整个类相关的操作。
class Dog:
total_dogs = 0
def __init__(self, name):
self.name = name
Dog.total_dogs += 1
@classmethod
def get_total_dogs(cls):
return cls.total_dogs
# 使用类方法获取总狗数
print(Dog.get_total_dogs())
工厂方法: 类方法可以用于创建类的实例,类似于工厂方法。
class Pizza:
def __init__(self, toppings):
self.toppings = toppings
@classmethod
def create_margherita(cls):
return cls(["cheese", "tomato"])
# 使用类方法创建披萨实例
margherita = Pizza.create_margherita()
class BankAccount:
# 类属性
interest_rate = 0.05
total_accounts = 0
def __init__(self, account_holder, balance=0):
# 实例属性
self.account_holder = account_holder
self.balance = balance
BankAccount.total_accounts += 1
# 实例方法
def deposit(self, amount):
self.balance += amount
print(f"Deposited ${amount}. New balance: ${self.balance}")
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
print(f"Withdrew ${amount}. New balance: ${self.balance}")
else:
print("Insufficient funds")
# 静态方法
@staticmethod
def is_valid_amount(amount):
return amount > 0
# 类方法
@classmethod
def get_total_accounts(cls):
return cls.total_accounts
# 类方法
@classmethod
def set_interest_rate(cls, new_rate):
cls.interest_rate = new_rate
print(f"New interest rate set to {new_rate}%")
# 创建账户实例
account1 = BankAccount("Alice", 1000)
# 使用实例方法
account1.deposit(500)
account1.withdraw(200)
# 使用静态方法
print(BankAccount.is_valid_amount(100)) # 输出 True
# 使用类方法
print(BankAccount.get_total_accounts()) # 输出 1
# 修改类属性
BankAccount.set_interest_rate(0.07)
在这个例子中:
interest_rate
和 total_accounts
分别存储了银行账户的利率和总账户数。account_holder
和 balance
分别表示账户持有人和账户余额。deposit
和 withdraw
用于存款和取款,并更新账户余额。is_valid_amount
检查给定金额是否为正数。get_total_accounts
返回创建的总账户数。set_interest_rate
用于修改利率。这个例子展示了如何在一个类中使用这五个成分,每个都有其特定的作用和用途。实际应用中,类的设计会更加复杂,但这个简单的例子足以说明这些成分的基本概念。如果不理解,我再举一个例子。
class Student:
# 类属性
passing_score = 60
total_students = 0
def __init__(self, name, age, score=0):
# 实例属性
self.name = name
self.age = age
self.score = score
Student.total_students += 1
# 实例方法
def study(self, hours):
self.score += hours
print(f"{self.name} studied for {hours} hours. New score: {self.score}")
def take_exam(self):
result = "Passed" if self.score >= Student.passing_score else "Failed"
print(f"{self.name} took the exam. Result: {result}")
# 静态方法
@staticmethod
def is_valid_score(score):
return 0 <= score <= 100
# 类方法
@classmethod
def get_total_students(cls):
return cls.total_students
# 类方法
@classmethod
def set_passing_score(cls, new_score):
cls.passing_score = new_score
print(f"New passing score set to {new_score}")
# 创建学生实例
student1 = Student("Alice", 20)
student2 = Student("Bob", 22, 75)
# 使用实例方法
student1.study(5)
student2.take_exam()
# 使用静态方法
print(Student.is_valid_score(85)) # 输出 True
# 使用类方法
print(Student.get_total_students()) # 输出 2
# 修改类属性
Student.set_passing_score(70)
在这个例子中:
passing_score
和 total_students
分别存储及格分数和总学生数。name
、age
和 score
分别表示学生的姓名、年龄和考试成绩。study
用于模拟学习,并更新考试成绩;take_exam
用于模拟考试,并输出考试结果。is_valid_score
检查给定分数是否在有效范围内。get_total_students
返回创建的总学生数;set_passing_score
用于修改及格分数。动态绑定是指在运行时给对象添加新的属性或方法。在Python中,对象是动态的,允许在运行时添加、修改或删除属性和方法。以下是关于动态绑定对象和方法的一些示例:
class MyClass:
def __init__(self, initial_value):
self.value = initial_value
# 创建对象
obj = MyClass(10)
# 动态添加属性
obj.new_attribute = "Hello, World!"
# 访问动态添加的属性
print(obj.new_attribute) # 输出: Hello, World!
在上面的例子中,我们创建了一个 MyClass
类的实例 obj
,然后动态地添加了一个名为 new_attribute
的属性。
class MyClass:
def greet(self):
print("Hello!")
# 创建对象
obj = MyClass()
# 定义一个新的方法
def farewell(self):
print("Goodbye!")
# 动态绑定新方法
obj.say_goodbye = farewell
# 调用动态绑定的方法
obj.say_goodbye() # 输出: Goodbye!
在上面的例子中,我们创建了一个 MyClass
类的实例 obj
,然后定义了一个新的函数 farewell
,最后将这个函数动态地绑定到对象的一个新方法 say_goodbye
上。
需要注意的是,动态绑定属性和方法的能力使得在运行时适应不同的需求变得更加灵活,但也需要小心使用,确保代码的可读性和维护性。在大多数情况下,静态定义的属性和方法更有助于代码的组织和理解。
在Python中,权限控制通过使用访问修饰符来实现,主要有三种类型的修饰符:公共修饰符、保护修饰符和私有修饰符。这些修饰符用于限制类的属性和方法的访问范围,以保障封装性和安全性。
在Python中,默认情况下,所有的属性和方法都是公共的,可以在类的内部和外部进行访问。
class MyClass:
def __init__(self):
self.public_variable = "Public Variable"
def public_method(self):
print("This is a public method")
# 示例
obj = MyClass()
print(obj.public_variable) # 可以访问
obj.public_method() # 可以调用
在属性或方法名称前加上一个下划线 _
表示该属性或方法是保护的,它只能在类的内部和子类中被访问。
class MyClass:
def __init__(self):
self._protected_variable = "Protected Variable"
def _protected_method(self):
print("This is a protected method")
# 示例
obj = MyClass()
print(obj._protected_variable) # 可以访问
obj._protected_method() # 可以调用
在属性或方法名称前加上两个下划线 __
表示该属性或方法是私有的,它只能在类的内部被访问。
class MyClass:
def __init__(self):
self.__private_variable = "Private Variable"
def __private_method(self):
print("This is a private method")
# 示例
obj = MyClass()
# print(obj.__private_variable) # 不能直接访问,会引发错误
# obj.__private_method() # 不能直接调用,会引发错误
尽管在Python中存在这些修饰符,但它们并不是强制性的,而是一种约定。即使使用了下划线 _
或双下划线 __
,仍然可以通过特定的方式进行访问。这种设计是基于信任的理念,即相信程序员会遵循这些约定来维护代码的封装性。
在面向对象编程中,子类(Subclass)是指从一个现有的类(称为父类或基类)继承特性并可能添加或修改这些特性的类。子类继承了父类的属性和方法,并且可以通过添加新的成员或修改继承的成员来扩展或改变其行为。这种继承关系是面向对象编程中一种重要的概念,用于实现代码的重用和扩展。
以下是一个简单的 Python 示例,演示了子类的概念:
# 父类
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")
# 创建父类实例
animal_obj = Animal("Generic Animal")
animal_obj.speak() # 输出: Generic Animal makes a sound
# 创建子类实例
dog_obj = Dog("Buddy")
dog_obj.speak() # 输出: Buddy barks
在这个例子中,Dog
类是 Animal
类的子类。Dog
类继承了 Animal
类的属性和方法,同时重写了 speak
方法,使其输出狗的特定声音。通过创建 Dog
类的实例,我们可以看到子类对象具有父类的特性,但也可以具有自己特定的行为。
子类可以继续被其他类继承,形成类的层次结构。这种继承关系允许在不影响父类的情况下,对子类进行修改和扩展。这提高了代码的可维护性、可重用性和可扩展性。
需要注意的是,Python 中使用 class 子类名(父类名):
的语法来定义子类,并使用 super()
函数调用父类的方法。
更多关于继承的知识请看python笔记10。
在 Python 中,类的属性可以通过以下方式进行设置:
在 __init__
方法中初始化属性: 通常,属性的初始化工作会在类的构造方法 __init__
中完成。在这个方法内,可以为对象的属性赋初值。这确保了在创建对象时,属性就被正确初始化。
class MyClass:
def __init__(self, name):
# 初始化属性
self.name = name
# 创建类的实例,并传递参数给 __init__ 方法
obj = MyClass("John")
# 访问属性
print(obj.name) # 输出: John
直接在类外部设置属性: 也可以在类的外部直接设置对象的属性。这种方式在对象创建后,随时都可以更改属性的值。
class MyClass:
pass
# 创建类的实例
obj = MyClass()
# 直接设置属性
obj.name = "John"
# 访问属性
print(obj.name) # 输出: John
需要注意的是,如果属性是以双下划线 __
开头的私有属性,建议在类的内部通过方法进行访问和修改,以保持封装性。这是为了遵循封装的原则,防止外部直接访问类的内部实现细节。
class MyClass:
def __init__(self, name):
# 使用私有属性
self.__name = name
def get_name(self):
# 获取私有属性值
return self.__name
def set_name(self, new_name):
# 设置私有属性值
self.__name = new_name
# 创建类的实例
obj = MyClass("John")
# 通过方法设置和获取私有属性值
obj.set_name("Jane")
print(obj.get_name()) # 输出: Jane
上述例子中,__name
是一个私有属性,通过 get_name
和 set_name
方法进行访问和修改。
总的来说,属性的设置可以通过构造方法 __init__
初始化,也可以在类的外部直接设置。对于私有属性,建议使用方法进行访问和修改,以提供更好的封装性。
@property和@property.setting
在 Python 中,@property
装饰器和 @property_name.setter
装饰器提供了一种属性的高级设置方式,允许你在访问或设置属性时执行特定的方法。这通常用于创建计算属性或实现更复杂的逻辑,而不仅仅是简单的属性访问和设置。
@property
装饰器:@property
装饰器用于将一个方法转换为只读属性。这意味着你可以像访问属性一样调用这个方法,而无需使用括号。
class MyClass:
def __init__(self, _name):
self._name = _name
@property
def name(self):
# 只读属性,可以通过 obj.name 访问
return self._name
# 创建类的实例
obj = MyClass("John")
# 通过只读属性访问
print(obj.name) # 输出: John
@property_name.setter
装饰器:@property_name.setter
装饰器用于定义与 @property
装饰器搭配使用的可写属性的设置方法。
class MyClass:
def __init__(self, _name):
self._name = _name
@property
def name(self):
# 只读属性,可以通过 obj.name 访问
return self._name
@name.setter
def name(self, new_name):
# 可写属性的设置方法
self._name = new_name
# 创建类的实例
obj = MyClass("John")
# 通过可写属性设置新值
obj.name = "Jane"
# 通过只读属性访问
print(obj.name) # 输出: Jane
在这个例子中,name
方法被 @property
装饰器标记为只读属性,而 @name.setter
装饰器定义了可写属性的设置方法。
这种方式允许你在获取或设置属性时执行一些逻辑,而不是简单地访问或修改属性的值。这对于实现一些计算属性或属性相关的逻辑非常有用。