面向对象+
1.@property装饰器
@property装饰器用于将一个方法转换为属性,使得可以像访问属性一样访问这个方法。它能够让方法在使用时看起来像一个简单的属性,而不是一个方法。
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return 3.14 * self.radius ** 2
circle = Circle(5)
print(circle.area) # 使用@property装饰器的方法被当作属性访问
在上面的代码中,area方法被@property装饰器修饰,使得我们可以像访问属性一样访问它。当我们通过circle.area访问area时,实际上会调用area()方法并返回结果。
2.slots
slots__是一个特殊的类属性,它允许我们限制在实例中可以添加的属性。通过使用__slots,我们可以减少对象的内存消耗,并限制属性的定义,防止意外添加新的属性。
class Person:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
person = Person('Alice', 25)
person.name = 'Bob' # 可以修改已定义的属性
person.gender = 'Female' # 由于gender未在__slots__中定义,会引发AttributeError
在上面的代码中,__slots__属性指定了Person类实例中允许的属性列表。在这个例子中,只有’name’和’age’是允许的属性。当我们尝试设置一个未在__slots__中定义的属性时,会引发AttributeError。
3.静态方法和类方法
静态方法(staticmethod)和类方法(classmethod)是与类相关联的方法,可以在不创建类实例的情况下使用。
静态方法用于在类级别上执行某些操作,而不需要访问实例属性或方法。静态方法不会自动传递任何参数,需要显式地指定参数。
类方法用于在类级别上执行操作,并且可以访问类的属性和方法。类方法的第一个参数通常被命名为cls,代表类本身。
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@classmethod
def multiply(cls, a, b):
return a * b
print(MathUtils.add(2, 3)) # 调用静态方法
print(MathUtils.multiply(2, 3)) # 调用类方法
在上面的代码中,add方法被定义为静态方法,可以直接通过类名调用。multiply方法被定义为类方法,并且可以通过类名调用。
4.类之间的关系
类之间可以有几种不同的关系,包括关联(association)、聚合(aggregation)、组合(composition)和继承(inheritance)。
关联:当一个类与另一个类有某种关系时,我们称之为关联关系。它可以是单向或双向的,表示对象之间有某种连接。例如,一个学生类可以与一个教师类相关联。
聚合:聚合关系表示一个类包含了其他类的对象,但是这些对象可以在其他地方被使用,它们之间的生命周期可以独立存在。例如,一个学校类可以包含多个学生类的对象,但学生也可以存在于其他地方。
组合:组合关系与聚合关系类似,表示一个类包含了其他类的对象,但是这些对象的生命周期与包含它们的类的生命周期相关联。如果一个类的对象被销毁,它包含的对象也会被销毁。例如,一个汽车类可以包含多个轮子类的对象,但是当汽车被销毁时,轮子也会被销毁。
继承:继承是面向对象编程中的一种重要关系,表示一个类可以继承另一个类的属性和方法。继承允许子类从父类继承公共的功能,并可以在子类中添加特定的功能或修改继承的功能。
class Teacher:
def __init__(self, name):
self.name = name
def teach(self):
print("Teaching...")
class Student:
def __init__(self, name):
self.name = name
def learn(self):
print("Learning...")
class School:
def __init__(self):
self.teacher = Teacher("Mr. Smith")
self.students = [Student("Alice"), Student("Bob")]
school = School()
school.teacher.teach() # 调用关联的Teacher类的方法
for student in school.students:
student.learn() # 调用关联的Student类的方法
在上面的代码中,School类与Teacher类和Student类有关联关系。School类包含了Teacher类的对象和Student类的多个对象。
5.继承和多态
继承允许一个类继承另一个类的属性和方法,并且可以在子类中添加新的属性和方法,或者修改继承的属性和方法。这种继承关系可以实现多态性,即不同的对象可以对相同的方法做出不同的响应。
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
pass
class Dog(Animal):
def sound(self):
return "Woof!"
class Cat(Animal):
def sound(self):
return "Meow!"
animals = [Dog("Buddy"), Cat("Kitty")]
for animal in animals:
print(animal.name + ": " + animal.sound()) # 多态性的体现
在上面的代码中,Animal类是一个基类,而Dog类和Cat类是Animal类的子类。每个子类都重写了基类的sound()方法以提供不同的声音。通过对Animal类的子类实例化,并使用相同的方法名称访问它们,可以看到多态性的效果。
练习
练习1:21点扑克,游戏规则:玩家和庄家会被发两张牌,然后玩家可以选择要牌(hit)或停牌(stand)。当玩家选择要牌时,他们会得到一张新牌,并检查是否爆牌。当玩家选择停牌时,庄家会开始抽牌直到达到17点或以上。然后,比较玩家和庄家的点数,根据规则判断输赢或平局。
import random
class Card:
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def get_value(self):
if self.rank in ["J", "Q", "K"]:
return 10
elif self.rank == "A":
return 11
else:
return int(self.rank)
def __str__(self):
return f"{self.rank} of {self.suit}"
class Deck:
def __init__(self):
ranks = [str(num) for num in range(2, 11)] + ["J", "Q", "K", "A"]
suits = ["Hearts", "Diamonds", "Clubs", "Spades"]
self.cards = [Card(rank, suit) for rank in ranks for suit in suits]
random.shuffle(self.cards)
def deal_card(self):
return self.cards.pop()
class Hand:
def __init__(self):
self.cards = []
def add_card(self, card):
self.cards.append(card)
def get_value(self):
value = sum([card.get_value() for card in self.cards])
num_aces = sum([1 for card in self.cards if card.rank == "A"])
while value > 21 and num_aces > 0:
value -= 10
num_aces -= 1
return value
def __str__(self):
return ", ".join([str(card) for card in self.cards])
class Game:
def __init__(self):
self.deck = Deck()
self.player_hand = Hand()
self.dealer_hand = Hand()
def play(self):
print("Welcome to 21-point Poker!")
self.player_hand.add_card(self.deck.deal_card())
self.player_hand.add_card(self.deck.deal_card())
self.dealer_hand.add_card(self.deck.deal_card())
self.dealer_hand.add_card(self.deck.deal_card())
self.show_initial_cards()
while True:
choice = input("Do you want to hit or stand? (h/s): ")
if choice.lower() == "h":
self.player_hand.add_card(self.deck.deal_card())
self.show_player_cards()
if self.player_hand.get_value() > 21:
self.player_busts()
break
elif choice.lower() == "s":
self.show_dealer_cards()
while self.dealer_hand.get_value() < 17:
self.dealer_hand.add_card(self.deck.deal_card())
self.show_dealer_cards()
if self.dealer_hand.get_value() > 21:
self.dealer_busts()
else:
self.compare_hands()
break
def show_initial_cards(self):
print("Player's cards:", self.player_hand)
print("Dealer's cards:", self.dealer_hand.cards[0])
def show_player_cards(self):
print("Player's cards:", self.player_hand)
def show_dealer_cards(self):
print("Dealer's cards:", self.dealer_hand)
def player_busts(self):
print("Player busts! You lose.")
def dealer_busts(self):
print("Dealer busts! You win.")
def compare_hands(self):
player_value = self.player_hand.get_value()
dealer_value = self.dealer_hand.get_value()
if player_value > dealer_value:
print("You win!")
elif player_value < dealer_value:
print("You lose.")
else:
print("Push! It's a tie.")
# 游戏开始
game = Game()
game.play()
练习2:工资结算系统
class Employee:
def __init__(self, name):
self.name = name
def calculate_salary(self):
pass
class Manager(Employee):
def calculate_salary(self):
return 15000
class Programmer(Employee):
def __init__(self, name, hours_worked):
super().__init__(name)
self.hours_worked = hours_worked
def calculate_salary(self):
hourly_rate = 150
return self.hours_worked * hourly_rate
class Salesperson(Employee):
def __init__(self, name, base_salary, sales_amount):
super().__init__(name)
self.base_salary = base_salary
self.sales_amount = sales_amount
def calculate_salary(self):
commission_rate = 0.05
return self.base_salary + self.sales_amount * commission_rate
# 输入员工信息
def input_employees():
employees = []
while True:
employee_type = input("请输入员工类型(1 - 部门经理,2 - 程序员,3 - 销售员):")
name = input("请输入员工姓名:")
if employee_type == "1":
employee = Manager(name)
elif employee_type == "2":
hours_worked = int(input("请输入工作小时数:"))
employee = Programmer(name, hours_worked)
elif employee_type == "3":
base_salary = int(input("请输入底薪:"))
sales_amount = int(input("请输入销售额:"))
employee = Salesperson(name, base_salary, sales_amount)
else:
print("无效的员工类型,请重新输入。")
continue
employees.append(employee)
more_employees = input("是否输入更多员工信息?(y/n):")
if more_employees.lower() != "y":
break
return employees
# 计算并输出员工月薪
def calculate_and_print_salaries(employees):
print("员工月薪如下:")
for employee in employees:
salary = employee.calculate_salary()
print(f"{employee.name}: {salary}")
employees = input_employees()
calculate_and_print_salaries(employees)
练习3:愤怒的小鸟,游戏规则:有一只小鸟和一些障碍物。
小鸟可以被发射,玩家可以控制发射角度和速度。
玩家需要用小鸟击中障碍物,使其倒下。
游戏结束条件为所有障碍物都倒下或小鸟用尽。
def launch_decorator(game_func):
def wrapper(self, angle, velocity):
if self.bird is not None:
self.bird.launch(angle, velocity)
game_func(self, angle, velocity)
return wrapper
def hit_decorator(game_func):
def wrapper(self):
if self.bird is not None and self.bird.is_launched:
game_func(self)
return wrapper
class Bird:
def __init__(self, name):
self.name = name
self.is_launched = False
def launch(self, angle, velocity):
self.is_launched = True
print(f"The bird '{self.name}' is launched with angle {angle} and velocity {velocity}!")
@hit_decorator
def hit_obstacle(self):
print(f"The bird '{self.name}' hit an obstacle!")
class Obstacle:
def __init__(self, name):
self.name = name
self.is_fallen = False
def fall(self):
self.is_fallen = True
print(f"The obstacle '{self.name}' has fallen!")
class AngryBirdsGame:
def __init__(self):
self.bird = None
self.obstacles = []
def add_bird(self, name):
self.bird = Bird(name)
def add_obstacle(self, name):
obstacle = Obstacle(name)
self.obstacles.append(obstacle)
@launch_decorator
def launch_bird(self, angle, velocity):
pass
@hit_decorator
def hit_obstacle(self):
pass
# 示例用法
game = AngryBirdsGame()
game.add_bird("Red")
game.add_obstacle("Pig")
game.launch_bird(45, 30) # 输出: The bird 'Red' is launched with angle 45 and velocity 30!
game.hit_obstacle() # 输出: The bird 'Red' hit an obstacle!
Day 9 is over!