一、类的概念
1. 在编程中,有一种范式遵循与蓝图和实例相同的原则。它被称为面向对象编程 (OOP)。在 OOP 中,蓝图称为类(class),实例称为对象(object)。
在 Python 中,可以使用 class 关键字+类名+冒号来定义一个类。
示例:
class Car:
2. 要向类添加属性,必须定义 __init__ 方法。此方法的第一个参数始终是 self,它表示类的实例。在 self 之后,指定要包含的属性。然后,在函数内部,为初始化对象的属性赋值,设置它们的初始状态。
示例1:
class Car:
#初始化属性
def __init__(self, brand, color): #第一个属性必须是self
self.brand = brand
self.color = color
#实例化对象
my_car = Car("Audi", "blue")
print(my_car) #跟java一样,对象无法直接打印
print(my_car.brand)
示例2:
class Car():
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
3. 除了属性之外,您还可以通过在类中定义函数来向类添加自定义行为。这些函数称为方法,应包含“self”参数以与类实例进行交互。您可以使用点 . 表示法来调用这些方法,类似于访问属性的方式。
class Car:
def __init__(self, brand, color): #第一个属性必须是self
self.brand = brand
self.color = color
def honk(self):
print("Beep, beep!")
my_car = Car("Audi", "blue")
my_car.honk() #Beep, beep!
函数和方法之间的主要区别在于,函数是独立的,可以自行调用,而方法与类相关联,只能通过其实例调用。这意味着,如果没有定义该方法的类的实例,则无法调用该方法。
二、继承
了解继承的原理,这是一种可以增强程序的多功能性和效率的 OOP 概念。
继承是一个关键概念,适用于以下情况:有一个具有已定义属性和行为的现有类,而需要一个不仅具有这些特征而且具有自己独特特征的新类。继承允许新类从现有类“继承”属性,同时根据需要添加或修改特定功能。
继承自其他类的类称为超类(superclass)或父类(parent)。相反,继承自其他类的类称为子类(subclass)或子类(child)。
class Animal:
def __init__ (self, name):
self.name = name
def move(self):
print("Moving")
# Inherits from Animal class
class Dog(Animal): #定义子类时,将父类名称放在括号中。
# Specific behavior
def bark(self):
print("Woof!")
# Creating an instance
my_dog = Dog("Bob")
# Inherited attribute and behavior
print(my_dog.name)
my_dog.move()
# Specific behavior
my_dog.bark()
如果我们不仅想继承属性,还想为子类添加特定属性,该怎么办?在这种情况下,我们在子类中定义一个 __init__ 方法。使用 super().__init__() 从父类继承属性,然后像往常一样定义任何其他属性。
#parent class
class Animal:
def __init__ (self, name):
self.name = name
def move(self):
print("Moving")
#child class
class Dog(Animal):
def __init__ (self, name, breed, age):
# Initialize attributes of the superclass
super(). init (name)
# Additional attributes specific to Dog
self.breed = breed
self.age = age
def bark(self):
print("Woof!")
my_dog = Dog("Jax", "Bulldog", 5) #inherited attribute
print(my_dog.name)
#Additional attributes
print(my_dog.breed)
print(my_dog.age)
方法覆盖是OOP中另一个关键概念——多态的演示。多态性允许对象以自己的方式使用方法,即使它们共享相同的名称。
在本例中,尽管animals列表中的每种动物可能属于不同的子类,但代码可以对每种动物调用sound(),而无需知道其特定类型。
# Parent class
class Animal:
def init (self, name):
self.name = name
# Generic sound method for any animal
def sound(self):
print("Making a sound")
# Child class Dog
class Dog(Animal):
def init (self, name, breed, age):
super(). init (name)
self.breed = breed
self.age = age
# Overridden sound method for Dog
def sound (self):
print("Woof!")
# Child class Cat
class Cat(Animal):
def init (self, name, breed, age):
super(). init (name)
self.breed = breed
self.age = age
# Overridden sound method for Cat
def sound(self):
print("Meow!")
# Creating instances
my_dog = Dog("3ax", "Bulldog", 5)
my_cat = Cat("Lily", "Ragdoll", 2)
animals = [my_dog, my_cat]
for animal in animals:
animal.sound()
三、数据隐藏
数据隐藏是使带有对象的代码(如游戏或应用程序)更安全、更清晰的关键思想。这意味着将对象的某些部分保持私有,以便只有某些部分的代码可以更改它们。这有助于防止错误并使代码易于管理。
数据隐藏有助于OOP中的封装,增强代码的安全性和健壮性。
在编程中,有时“保护”某些类属性和方法不被类外部访问是至关重要的。这被称为数据隐藏,并确保数据的完整性和安全性,防止意外或有害的修改。
在Python中,数据隐藏有两个级别。第一种方法是在属性前加上一个下划线_,表示它只用于内部使用,应该被视为“受保护的”。
让我们使用odometer属性进行此更改:
class Car:
def __init__ (self, model, year, odometer):
self.model = model
self.year = year
# Making the odometer attribute 'protected' 加单下划线用于保护
self._odometer = odometer
def describe_car(self):
print(self.year, self.model)
def read_odometer(self):
print("Odometer:", self._odometer, "miles")
my_car = Car('Audi’, 2020, 15000)
my_car.describe_car()
my_car.read_odometer()
带有单个下划线的属性是可访问的,但被认为是受约定保护的,表明它们是供内部使用的,应该在类外部谨慎访问。
要访问类外部的受保护属性,请使用单个下划线前缀,因为这是属性名称的一部分。
class Car:
def __init__ (self, model, year, odometer):
self.model = model
self.year = year
# Making the odometer attribute 'protected'
self._odometer = odometer
def describe_car(self):
print(self.year, self.model)
def read_odometer(self):
print("Odometer:", self._odometer, "miles")
my_car = Car("Audi", 2020, 15000)
#accessing the protected attribute
print(my_car._odometer)
数据隐藏的下一层涉及将属性设置为私有。这是通过在属性名前加上两个下划线来实现的(例如,__attribute)。在这种情况下,与受保护的属性不同,这不仅仅是一种约定——它通过名称混淆限制了它在类外部的访问,从而增强了数据保护和封装。此方法用于敏感或内部数据,强烈阻止外部访问。
class Car:
def __init__(self, model, year, odometer):
self.model = model
self.year = year
# Making the odometer attribute 'private'
self.__odometer = odometer
从类外部访问带有双下划线的私有属性会导致错误,但可以在类方法中访问它。这演示了封装,保护敏感数据不受外部访问,并确保它只能通过特定的方法访问,与面向对象编程原则保持一致。
class Car:
def __init__(self, model, year, odometer):
self.model = model
self.year = year
# Making the odometer attribute 'private'
self.__odometer = odometer
def describe_car(self):
print(self.year, self.model)
def read_odometer(self):
print("Odometer:", self.__odometer, "miles")
my_car = Car('Audi’, 2020, 15000)
#accessing the attribute within method
my_car.read_odometer()
#error
print(mycar.__odometer)
在Python中,通常不鼓励直接从类外部访问私有属性。但是,Python对私有属性使用了名称混淆,这意味着您可以在必要时从类外部使用特定的命名约定访问它们。
class Car:
def __init__(self, model, year, odometer):
self.model = model
self.year = year
# Making the odometer attribute 'private'
self.__odometer = odometer
def describe_car(self):
print(self.year, self.model)
def read_odometer(self):
print("Odometer:", self.__odometer, "miles")
my_car = Car("Audi", 2020, 15000)
# accesing using name mangling
print(my_car._Car__odometer)
总结:
🌟数据隐藏是面向对象编程的关键,用于编写安全和有组织的代码
🌟使用单个下划线(_)表示属性或方法是受保护的,仅供内部使用
🌟双下划线(__)使属性或方法私有,限制对类本身的访问,从而增强了数据安全性
🌟这些约定有助于管理访问并在代码中保持清晰的结构
类方法在类本身上调用,而不是在单个实例上调用。这允许在不创建类实例的情况下使用它们。它们对于与整个类相关的操作特别有用,而不是仅限于单个对象的操作。
类方法是使用@classmethod装饰器创建的,并接受cls参数,该参数引用类本身。
要调用类方法,不需要创建类的实例。相反,只需使用类名,后跟一个点和类方法名。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
#regular method
def describe_book(self):
print(self.title, 'by', self.author)
#class method
@classmethod
def books_in_series(cls, series_name, number_of_books):
print("There are", number_of_books, "books in the", series_name, "series")
# Creating an instance of Book
my_book = Book("Harry Potter and the Sorcerer's Stone", "J.K. Rowling")
# Using the instance method to describe the book
my_book.describe_book()
# Using the class method to display information about the series(不需要创建实例)
Book.books_in_series("Harry Potter", 7)
实例共享类所拥有的一切,包括类的方法。这意味着您还需要在实例上调用类方法。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
#regular method
def describe_book(self):
print(self.title, 'by', self.author)
#class method
@classmethod
def books_in_series(cls, series_name, number_of_books):
print("There are", number_of_books, "books in the", series_name, "series")
# Creating an instance of Book
my_book = Book("Harry Potter and the Sorcerer's Stone", "J.K. Rowling")
# Using the instance method to describe the book
my_book.describe_book()
# calling the class method on the instance(需要创建实例)
my_book.books_in_series("Harry Potter", 7)
静态方法类似于类方法,除了它们不接受任何额外的参数;它们与属于类的普通函数相同。
它们被标记为@staticmethod装饰器。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
#regular method
def describe_book(self):
print(self.title, 'by', self.author)
#static method
@staticmethod
def books_in_series(series_name, number_of_books): #与classmethod相比,没有cls参数
print("There are", number_of_books, "books in the", series_name, "series")
# Creating an instance of Book
my_book = Book("Harry Potter and the Sorcerer's Stone", "J.K. Rowling")
# Using the instance method to describe the book
my_book.describe_book()
# calling the static method
my_book.books_in_series("Harry Potter", 7)
什么时候应该使用静态方法而不是类方法?静态方法不接受cls参数,这意味着它们不能访问或修改类的状态。当您需要的功能不依赖于类的行为或实例状态并且不影响它时,它们非常有用。本质上,静态方法适合于自包含的任务,不需要了解类或实例。
总结:
🌟类方法在类本身上调用,而不是在单个实例上调用
🌟类方法使用@classmethod装饰器定义,并接受cls参数
🌟使用@staticmethod装饰器定义的静态方法类似于类方法,但不能访问类的状态