python学习 --day4

一. Python类和对象

  • 什么是对象
    • 对象是指现实中的物体或实体
  • 什么是面向对象
    • 把一切看成对象(实例),用各种对象之间的关系来描述事务。
  • 对象都有什么特征
    • 对象有很多属性(名词)
    • 姓名, 年龄, 性别,
    • 对象有很多行为(动作,动词)
    • 学习,吃饭,睡觉,踢球, 工作
  • 什么是类:
    • 拥有相同属性和行为的对象分为一组,即为一个类
    • 类是用来描述对象的工具,用类可以创建此类的对象(实例)

1.类

类是创建对象的 ”模板”。

  • 数据成员:表明事物的特征。 相当于变量
  • 方法成员:表明事物的功能。 相当于函数
  • 通过class关键字定义类

示例代码:

class Dog: # 定义一个Dog类
	pass
class Person:
	def __init__(self, name, age):
	self.name = name
	self.age = age
def introduce(self):
	print(f"My name is {self.name} and I am {self.age} years old.")

类的创建的说明:

  • 类名必须为标识符(与变量的命名相同,建议首字母大写)
  • 类名实质上就是变量,它绑定一个类

2. 实例化对象(构造函数)

(1) 构造函数调用表达式
变量 = 类名([参数])
(2) 说明

  • 变量存储的是实例化后的对象地址。
  • 类名后面的参数按照构造方法的形参传递
  • 对象是类的实例,具有类定义的属性和方法。
  • 通过调用类的构造函数来创建对象。
    每个对象都有自己的状态,但共享相同的方法定义。
    示例代码:
class Dog:
	pass

创建第一个实例:
dog1 = Dog()
print(id(dog1)) # 打印这个对象的ID

创建第二个实例对象
dog2 = Dog() # dog2 绑定一个Dog类型的对象
print(id(dog2))
lst1 = list()
print(id(lst1))
lst2 = list()
print(id(lst2))

class Person:
	def __init__(self, name, age):
		self.name = name
		self.age = age
	def introduce(self):
		print(f"My name is {self.name} and I am {self.age} years old.")
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

实例说明:

  • 实例有自己的作用域和名字空间,可以为该实例添加实例变量(也叫属性)
  • 实例可以调用类方法和实例方法
  • 实例可以访问类变量和实例变量

3. 属性和方法

3.1属性

每个实例可以有自己的变量,称为实例变量(也叫属性)

  • 属性的使用语法
实例.属性名
  • 属性的赋值规则:

首次为属性赋值则创建此属性.
再次为属性赋值则改变属性的绑定关系.

实例代码:
class Dog:
	def eat(self, food):
		self.food = food
		print(self.color, '的', self.kinds, '正在吃', food)
	pass
# 创建一个实例:
dog1 = Dog()
dog1.kinds = "京巴" # 添加属性
dog1.color = "白色"
dog1.color = "黄色" # 改变属性的绑定关系
print(dog1.color, '的', dog1.kinds)

3.2 方法

class 类名(继承列表):
def 实例方法名(self, 参数1, 参数2, …):
“文档字符串”
语句块

  • 实例方法的作用

    • 用于描述一个对象的行为,让此类型的全部对象都拥有相同的行为
  • 实例方法说明

    • 实例方法的实质是函数,是定义在类内的函数
    • 实例方法至少有一个形参,第一个形参绑定调用这个方法的实例,一般命名为"self"
    • 实例方法名是类属性
    • 实例方法的调用语法
    • 实例.实例方法名(调用传参)
实例代码:
class Dog:
"""这是一个种小动物的定义
这种动物是狗(犬)类,用于创建各种各样的小狗
"""
	def eat(self, food):
	'''此方法用来描述小狗吃东西的行为'''
		print("小狗正在吃", food)
	def sleep(self, hour):
		print("小狗睡了", hour, "小时!")
	def play(self, obj):
		print("小狗正在玩", obj)
dog1 = Dog()
dog1.eat("骨头") #小狗正在吃 骨头
dog1.sleep(1) #小狗睡了 1 小时!
dog1.play('球') #小狗正在玩 球

dog2 = Dog()
dog2.eat("窝头")#小狗正在吃 窝头
dog2.sleep(2)#小狗睡了 2 小时!
dog2.play('飞盘')#小狗正在玩 飞盘
>>> help(Dog) # 可以看到Dog类的文档信息

4.类属性

  • 类方法是用于描述类的行为的方法,类方法属于类,不属于该类创建的对象
  • 说明
    • 类方法需要使用@classmethod装饰器定义
    • 类方法至少有一个形参,第一个形参用于绑定类,约定写为’cls’
    • 类和该类的实例都可以调用类方法
    • 类方法不能访问此类创建的对象的实例属性
类属性实例代码
class Human:
	total_count = 0 # 创建类属性
	def __init__(self, name):
		self.name = name
		print(Human.total_count)
h1 = Human("小张")
print(h1.total_count)

5.类方法

  • 类方法是用于描述类的行为的方法,类方法属于类,不属于该类创建的对象
  • 说明
    • 类方法需要使用@classmethod装饰器定义
    • 类方法至少有一个形参,第一个形参用于绑定类,约定写为’cls’
    • 类和该类的实例都可以调用类方法
    • 类方法不能访问此类创建的对象的实例属性
类方法示例1
class A:
	v = 0
	@classmethod
	def set_v(cls, value):
		cls.v = value
	@classmethod
	def get_v(cls):
		return cls.v

print(A.get_v()) #0

A.set_v(100)
print(A.get_v()) #100

a = A()
print(a.get_v()) #100
类方法实例2
class MyClass:
	class_attr = 0 # 类属性
	def __init__(self, value):
		self.instance_attr = value # 实例属性
	@classmethod
	def modify_class_attr(cls, new_value):
		cls.class_attr = new_value
		print(f"类属性已修改为: {cls.class_attr}")
	
	@classmethod
	def try_modify_instance_attr(cls):
	try:
		cls.instance_attr = 10 # 尝试修改实例属性(会失败)
	except AttributeError as e:
		print(f"错误: {e}")
		
	def show_attrs(self):
		print(f"实例属性: {self.instance_attr}")
		print(f"类属性: {self.class_attr}")

# 创建类的实例
obj = MyClass(5)

# 调用类方法修改类属性
MyClass.modify_class_attr(20) # 输出: 类属性已修改为: 20

obj.show_attrs()
# 输出:
# 实例属性: 5
# 类属性: 20
# 调用类方法尝试修改实例属性
MyClass.try_modify_instance_attr()
# 输出: 错误: type object 'MyClass' has no attribute 'instance_attr'
# 尝试调用类方法修改实例属性
obj.try_modify_instance_attr()
# 输出: 错误: type object 'MyClass' has no attribute 'instance_attr'

5.1 cls --作用

  • 在Python中,cls 是一个约定俗成的名称,用于表示类本身。在类方法(使用 @classmethod 装饰的方法)中,cls 作为第一个参数传递给方法。这使得类方法可以访问和修改类属性以及调用其他类方法,而不需要引用具体的实例。

  • cls 的作用

      1. 访问类属性:类方法可以通过 cls 访问和修改类属性。
      1. 调用类方法:类方法可以通过 cls 调用其他类方法。
      1. 创建类实例:类方法可以使用 cls 来创建类的实例。
示例
class MyClass:
	class_attr = 0 # 类属性
	def __init__(self, value):
		self.instance_attr = value # 实例属性
		
	@classmethod
	def modify_class_attr(cls, new_value):
		cls.class_attr = new_value
		print(f"类属性已修改为: {cls.class_attr}")
		
	@classmethod
	def show_class_attr(cls):
		print(f"类属性当前值: {cls.class_attr}")
		
	@classmethod
	def create_instance(cls, value):
		# 使用 cls 创建类实例
		return cls(value)

# 调用类方法修改类属性
MyClass.modify_class_attr(20) # 输出: 类属性已修改为: 20

# 调用类方法显示类属性
MyClass.show_class_attr() # 输出: 类属性当前值: 20

# 使用类方法创建类的实例
new_instance = MyClass.create_instance(10)
print(f"新实例的实例属性: {new_instance.instance_attr}") # 输出: 新实例的实例属性: 10
print(f"新实例的类属性: {new_instance.class_attr}") # 输出: 新实例的类属性: 20

5.2 静态方法 @staticmethod

  • 静态方法是定义在类的内部函数,此函数的作用域是类的内部
  • 说明
    • 静态方法需要使用@staticmethod装饰器定义
    • 静态方法与普通函数定义相同,不需要传入self实例参数和cls类参数
    • 静态方法只能凭借该类或类创建的实例调用
    • 静态方法不能访问类属性和实例属性
静态方法示例
class A:
	class_attr = 42 # 类属性
	def __init__(self, value):
		self.instance_attr = value # 实例属性
		
	@staticmethod
	def myadd(a, b):
	#只能访问传递的参数,不能访问类属性和实例属性
		return a + b

#创建类实例
a = A(10)

#调用静态方法
print(A.myadd(100, 200)) # 输出: 300
print(a.myadd(300, 400)) # 输出: 700


#尝试在静态方法内访问类属性或实例属性(会导致错误)
class B:
	class_attr = 42
	def __init__(self, value):
		self.instance_attr = value
	@staticmethod
	def myadd(a, b):
	#以下访问会导致错误
		return a + b + B.class_attr # return a + b + self.instance_attr
		return a + b

#创建类实例
b = B(10)

#调用静态方法
print(B.myadd(100, 200)) # 输出: 300
print(b.myadd(300, 400)) # 输出: 700

6.魔术方法

  • Python中的魔术方法(Magic Methods)是一种特殊的方法,它们以双下划线开头和结尾,例如__init__,str,__add__等。这些方法允许您自定义类的行为,以便与内置Python功能(如+运算符、迭代、字符串表示等)交互。

  • 以下是一些常用的Python魔术方法:

  1. init(self, …): 初始化对象,通常用于设置对象的属性。
  2. str(self): 定义对象的字符串表示形式,可通过str(object)或print(object)调用。例
    如,您可以返回一个字符串,描述对象的属性。
  3. repr(self): 定义对象的“官方”字符串表示形式,通常用于调试。可通过repr(object)调
    用。
  4. len(self): 定义对象的长度,可通过len(object)调用。通常在自定义容器类中使用。
  5. getitem(self, key): 定义对象的索引操作,使对象可被像列表或字典一样索引。例如,
    object[key]。
  6. setitem(self, key, value): 定义对象的赋值操作,使对象可像列表或字典一样赋值。例
    如,object[key] = value。
  7. delitem(self, key): 定义对象的删除操作,使对象可像列表或字典一样删除元素。例如,
    del object[key]。
  8. iter(self): 定义迭代器,使对象可迭代,可用于for循环。
  9. next(self): 定义迭代器的下一个元素,通常与__iter__一起使用。
  10. add(self, other): 定义对象相加的行为,使对象可以使用+运算符相加。例如,object1+ object2。
  11. sub(self, other): 定义对象相减的行为,使对象可以使用-运算符相减。
  12. eq(self, other): 定义对象相等性的行为,使对象可以使用==运算符比较。
  13. lt(self, other): 定义对象小于其他对象的行为,使对象可以使用<运算符比较。
  14. gt(self, other): 定义对象大于其他对象的行为,使对象可以使用>运算符比较。

二.继承,封装,多态

什么是继承/派生

  • 继承是从已有的类中派生出新的类,新类具有原类的数据属性和行为,并能扩展新的能力。
  • 派生类就是从一个已有类中衍生出新类,在新的类上可以添加新的属性和行为
  • 为什么继承/派生
    • 继承的目的是延续旧的类的功能
    • 派生的目地是在旧类的基础上添加新的功能
  • 继承/派生的作用
    • 用继承派生机制,可以将一些共有功能加在基类中。实现代码的共享。
    • 在不改变基类的代码的基础上改变原有类的功能

1.单继承

  • 单继承的语法:
class 类名(基类名):
语句块
  • 单继承说明:单继承是指派生类由一个基类衍生出来的

2.多继承

Python支持多继承形式。多继承的类定义形如下例:

class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
  • 需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索, 即方法在子类中未找到时,从左到右查找父类中是否包含方法。

3.覆盖 override

  • 覆盖是指在有继承关系的类中,子类中实现了与基类同名的方法,在子类的实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫覆盖
  • 作用:
    实现和父类同名,但功能不同的方法
覆盖示例
class A:
	def work(self):
		print("A.work 被调用!")
class B(A):
	'''B类继承自A类'''
	def work(self):
		print("B.work 被调用!!!")
	pass
b = B()
b.work() # 请问调用谁? B
a = A()

3.1 super函数 – 调用父类方法

  • super() 函数是用于调用父类(超类)的一个方法。

  • super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

  • super() 方法的语法:

    • 在子类方法中可以使用super().add()调用父类中已被覆盖的方法
    • 可以使用super(Child, obj).myMethod()用子类对象调用父类已被覆盖的方法
实例1
class A:
	def add(self, x):
		y = x+1
		print(y)
class B(A):
	def add(self, x):
		print("子类方法")
		super().add(x)
b = B()
b.add(2) # 3
实例2
class Parent: # 定义父类
	def myMethod(self):
		print ('调用父类方法')
class Child(Parent): # 定义子类
	def myMethod(self):
		print ('调用子类方法')
		
c = Child()# 子类实例
c.myMethod()# 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法

4.封装–enclosure

  • 封装是指隐藏类的实现细节,让使用者不用关心这些细节;

  • 封装的目的是让使用者通过尽可能少的方法(或属性)操作对象

  • Python的封装是假的(模拟的)封装

  • 私有属性和方法

    • python类中以双下划线(__)开头,不以双下划线结尾的标识符为私有成员,私有成员只能使用方法来进行访问和修改
      • 以__开头的属性为类的私有属性,在子类和类外部无法直接使用
      • 以__开头的方法为私有方法,在子类和类外部无法直接调用
代码实例:
class A:
	def __init__(self):
		self.__p1 = 100 # 私有属性
	def __m1(self): # 私有方法
		print("__m1(self) 方法被调用")
	def showA(self):
		self.__m1()
		print("self.__p1 = ", self.__p1)
		
class B(A):
	def __init__(self):
		super().__init__()
	def showB(self):
		self.__m1() # 出错,不允许调用
		print("self.__p1 = ", self.__p1) # 出错,不允许调用
		# self._A__m1() # 正常调用
		# print("self.__p1 =", self._A__p1) # 正常访问

a = A()
a.showA()
a.__m1() # 出错,不允许调用
v = self.__p1 # 出错,不允许调用
b = B()
b.showB()
# 访问私有属性
print(a._A__p1) # 输出: 100
# 调用私有方法
a._A__m1() # 输出: __m1(self) 方法被调用
# 不推荐了解就行

5 多态 – polymorphic

  • 什么是多态:
    • 字面意思"多种状态"
    • 多态是指在有继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态
  • 状态:
    • 静态(编译时状态)
    • 动态(运行时状态)
  • 多态说明:
    • 多态调用的方法与对象相关,不与类型相关
    • Python的全部对象都只有"运行时状态(动态)“, 没有"C++语言"里的"编译时状态(静态)”
多态示例:
class Shape:
	def draw(self):
		print("Shape的draw()被调用")
		
class Point(Shape):
	def draw(self):
		print("正在画一个点!")
class Circle(Point):
	def draw(self):
		print("正在画一个圆!")
		
def my_draw(s):
	s.draw() # 此处显示出多态
	
shapes1 = Circle()
shapes2 = Point()
my_draw(shapes1) # 调用Circle 类中的draw
my_draw(shapes2) # Point 类中的draw

三.Python迭代器与生成器

1. 迭代器 Iterator

  • 什么是迭代器

    • 迭代器是访问可迭代对象的工具
    • 迭代器是指用 iter(obj) 函数返回的对象(实例)
    • 迭代器可以用next(it)函数获取可迭代对象的数据
  • 迭代器函数iter和next

    • iter(iterable) :从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象

    • next(iterator):从迭代器iterator中获取下一个记录,如果无法获取一下条记录,则触发StopIteration 异常

  • 迭代器说明

    • 迭代器只能往前取值,不会后退
    • 用iter函数可以返回一个可迭代对象的迭代器

2. 生成器

  • 生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。
  • yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
  • 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
  • 每次使用 yield 语句生产一个值后,函数都将暂停执行,等待被重新唤醒。
  • yield 语句相比于 return 语句,差别就在于 yield 语句返回的是可迭代对象,而 return 返回的为不可迭代对象。
  • 每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。
yield 语句的语法
yield 表达式
生成器函数示例1:
## 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象
def myrange(stop):
	i = 0
	while i < stop:
		yield i # 为 遍历次生产器的for 语句提供数据
		i += 1
for x in myrange(5):
	print('x=', x)

# 创建一个生成器对象
gen = myrange(5)
# 使用 next() 函数迭代生成器
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))

四. python 函数式编程

  • Python 的函数式编程是一种编程范式,它把计算视为数学函数的求值,避免了状态变化和可变数据。函数式编程在 Python 中并不是唯一的方法,但它提供了一些非常强大的工具以简化代码的结构和可读性。

Python 中的函数式编程特性:

  1. 高阶函数:可以接受函数作为参数,或返回一个函数的函数。
  2. 匿名函数(Lambda 函数):使用 lambda 关键字定义的简单函数。
  3. 函数组合:将多个函数结合起来形成新的函数。
  4. 惰性求值:使用生成器和迭代器来生成值,而不是一次生成所有值。
  5. 不变性:函数式编程强调函数调用产生的新值,而非修改现有值。

实例

下面是一些示例,展示了 Python 中函数式编程的使用。

  1. 高阶函数
def apply_function(func, value):
    return func(value)

def square(x):
    return x * x

print(apply_function(square, 5))  # 输出: 25
  1. 匿名函数
# 使用 lambda 表达式定义匿名函数
add = lambda x, y: x + y
print(add(2, 3))  # 输出: 5

# 在过滤操作中使用匿名函数
numbers = [1, 2, 3, 4, 5]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # 输出: [2, 4]
  1. 函数组合
def double(x):
    return x * 2

def add_three(x):
    return x + 3

def combined_function(x):
    return add_three(double(x))

print(combined_function(5))  # 输出: 13
  1. 使用生成器实现惰性求值
def square_generator(n):
    for i in range(n):
        yield i * i

squares = square_generator(5)
for square in squares:
    print(square)  # 输出: 0, 1, 4, 9, 16
  1. 使用 reduce 函数进行聚合
from functools import reduce

# 计算列表数字的乘积
numbers = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, numbers)
print(product)  # 输出: 24

五. 内置高阶函数

  • 定义:将函数作为参数或返回值的函数。
  • 常用:
    • (1)map(函数,可迭代对象)
      使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对
      象。
    • (2)filter(函数,可迭代对象)
      根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
    • (3)sorted(可迭代对象, key=函数, reverse=True)排序,返回值为排序后的列表结果。
    • (4)max(可迭代对象, key = 函数)根据函数获取可迭代对象的最大值。
    • (5)min(可迭代对象,key = 函数)根据函数获取可迭代对象的最小值。
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,异常处理是非常重要的一部分。当程序运行时如果出现错误,如果没有异常处理,程序就会崩溃。为了避免这种情况,Python提供了异常处理机制。 在Python中,异常处理语句使用 `try` 和 `except` 关键字来实现。`try` 语句块中包含可能会发生异常的代码,如果这段代码出现了异常,则会跳转到 `except` 语句块中执行异常处理代码。 下面是一个简单的例子: ```python try: num = int(input("请输入一个整数:")) print(10/num) except ZeroDivisionError: print("除数不能为0") except ValueError: print("输入的不是整数") ``` 在上面的代码中,我们尝试将用户输入的字符串转换为整数,并将其用作除数计算 10/num。如果用户输入的是 0,则会触发 ZeroDivisionError 异常。如果用户输入的不是整数,则会触发 ValueError 异常。如果发生异常,则会跳转到对应的 except 语句块中执行处理代码。 除了可以指定具体的异常类型,也可以使用 `except Exception` 来捕获所有异常。例如: ```python try: num = int(input("请输入一个整数:")) print(10/num) except Exception as e: print("发生异常:", e) ``` 在上面的代码中,如果发生任何异常,都会跳转到 `except` 语句块中执行处理代码,并将异常信息打印出来。 除了 `try` 和 `except`,还有 `finally` 关键字,它指定的代码块无论是否发生异常都会执行。例如: ```python try: num = int(input("请输入一个整数:")) print(10/num) except Exception as e: print("发生异常:", e) finally: print("程序执行完毕") ``` 在上面的代码中,无论是否发生异常,都会执行 `finally` 中的代码,即输出“程序执行完毕”。 总之,在Python中,异常处理是非常重要的一部分,它可以有效避免程序崩溃,提高程序的健壮性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值