02-python进阶笔记

python进阶笔记

面向对象

思想:找人帮我做事

  1. 面向过程:一步一步亲力亲为

面向对象三大特征:封装性,继承性,多态性

类和对象

函数是一个封装

类也是一个更大封装

类:

  1. 属性:事物的描述信息
  2. 行为:事物的行动能力
类-:具有单个或者多个属性或者方法的集合体的统称,是抽象的.
不能直接使用.
类相当于制造飞机的图纸,是负责创建对象

对象:

  1. 对象是由类创建出的一个具体存在,
  2. 可以直接使用
  3. 由哪一个类创建,就具有哪一个类的属性和行为
  4. 对象就像用图纸造出的飞机

类和对象的关系

  • 类是模板,对象是根据类创建出来的
  • 先有类,再有对象
  • 一个类可以创建多个对象

定义

  • 类名用大驼峰法定义(首字母大写)
  • 属性--事物的特征
  • 方法--事物具有的行为

创建类

class Fun(object)  # 定义类名
	#定义类的属性
	age = 10       #---实例属性
    # 定义类的方法
    def FunCement(self,参数): #默认要有self这是对象的
        print('行为') #行为的具体表现
        
lo = Fun() # lo是对象,Fun()是调用类,来创建对象lo,此时self是lo
l1 = Fun() # l1是对象,Fun()是调用类,来创建对象l1,此时self是l1  
print(Fun.age)

使用类

# 在上面创建好类之后,目前只是将对象给创建出来
# 接下来是使用

lo.FunCement()
# 会打印出'行为',也就是使用函数FunCement()
# 函数里面可以传参数
# 其中由于FunCement(self)绑定fo,此时如果FunCement(self)函数里面
# 使用self就表示调用对象自己

l1.FunCement()
# 会打印出'行为',也就是使用函数FunCement()
# 函数里面可以传参数
# 其中由于FunCement(self)绑定l1,此时如果FunCement(self)函数里面
# 使用self就表示调用对象自己

__init__的定义

class 类名(object): 
	def __init__(self):
    	print('这里什么时候会被打印?') 
    	# 直接创建对象 
    	# 使用对象调用__init__方法
  • 在创建对象时,没有调用__init__方法的前提下,就直接把里面的函数输出了
class Cat(object): 

	"""模拟猫咪的尝试"""
    def __init__(self,name, age): 
    	self.name = name # 实例属性 
    	self.age = age # 实例属性 
    	
    def sleep(self): # 实例方法 
    """猫咪被命令睡觉""" 
    	print('%d 岁的 %s猫 正在沙发上睡懒觉' % (self.age, self.name)) 
    	
    def eat(self, food): # 实例方法 
    	"""猫咪被命令吃东西""" 
    	self.food = food
    	print(f'{self.age}岁的{self.name}猫 在吃{self.food}')
    	
    	
    	
cat = Cat('Jack', 4) 

cat.sleep() # -如果在方法中使用self.food,会报错.因为food是在下面				#用eat方法之后才有的传参,进去被定义

cat.eat('沙拉')


上面的案例, 创建的每一个实例对象name都叫做Tom, age 都是3岁, 这个是不满足于日常需求的,
通过我们创建的不同实例, 自身的属性都可以不一样, 那么, 我们的写法就得不一样

总结

在创建一个对象的时候, 程序会做两个动作

  1. 在内存中为对象分配空间
  2. 调用初始化方法__init__为对象初始化
    因此, 通常也会把: 1. 创建出来的对象叫做类的实例
  3. 创建对象的动作叫做实例化
  4. 对象的属性叫做实例属性
  5. 对象调用的方法叫做实例方法
    在程序执行时: 1. 对象各自拥有自己的实例属性
  6. 调用对象方法, 可以通过self.
    来访问自己的属性

?函数里面能定义函数吗?

回答:----可以

?注意事项?

class Demo(objet):
	def __init__(self,name)
		self.name = name
		# name = name   是错误的,属性没有绑定对象,

self

由哪一个对象的调用方法,方法内的self就是哪一个对象

  1. 在封装方法的内部,self就表示当前调用方法的对象自己
  2. 在调用方法时,程序员不需要传递self参数
  3. 所谓的self,可以理解为自己
  4. 某个对象调用方法时,python解释器回吧这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

init

构造方法,初始化方法

  1. 类有一个名为__init__的魔法方法,该方法在类的实例化时会自动调用

  2. class 类名(Object):
    	def __init__(self):
    		print('一旦实例化就会被调用')
    
    
    f = 类名()
    
    
  3. 在创建对象时,没有调用__init_-方法的前提下,直接把__init里面的代码输出了

    class Cat(object):
    	"""模拟猫咪的尝试"""
    	def __init__(self, name, age):
    		self.name = name # 实例属性
    		self.age = age # 实例属性
    	def sleep(self): # 实例方法
    		"""猫咪被命令睡觉"""
    		print('%d 岁的 %s猫 正在沙发上睡懒觉' % (self.age, self.name))
    	def eat(self, food): # 实例方法
    		"""猫咪被命令吃东西"""
    		self.food = food
    		print('%d 岁的 %s猫 在吃 %s' % (self.age, self.name, self.food))
    
    cat = Cat('Jack', 4)
    cat.sleep()
    cat.eat('沙拉')
    
  4. 在创建对象时候,程序会做两个动作

    1. 在内存中为对象分配空间
    2. 调用初始化方法init为对象初始化
  5. 总称

    • 创建出来的对象叫做类的实例化
    • 创建对象的动作叫做实例化
    • 对象的属性叫做实例属性
    • 对象调用的方法叫做实例方法
  6. 在程序执行时

  • 对象各自拥有自己的实例属性
  • 调用对象方法,可以通过self.来访问自己的属性,来调用自己的方法

str方法

class Cat(object):
	def __init__(self):
		print('初始化方法')
	def __str__(self):
		print('1')
		return '这是对象返回的内容'
		
		
cat = Cat()
print(cat)
  • 在python中方法名如果是__xxxx__() 的,那么就有特殊的功能,因此叫做“魔法”方法
  • 当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__(self) 方
  • 法,那么就会打印从在这个方法中 return 的数据
  • str 方法通常返回一个字符串,作为这个对象的描述信息

del方法

在对象销毁时自动使用

class Cat(object):
	def __init__(self):
	print('初始化方法')
	def __del__(self):
	print('什么时候调用?')
	
	
cat = Cat()
print('*' * 50)
# del cat 加个这个会是怎样的
  • 此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释
    放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回
    收时自动触发执行的。
  • 当有变量保存了一个对象的引用时,此对象的引用计数就会加1;
    当使用del() 删除变量指向的对象时,则会减少对象的引用计数。如果对象的引用计数不为1,那么
    会让这个对象的引用计数减1,当对象的引用计数为0的时候,则对象才会被真正删除(内存被回
    收)。

私有属性和私有方法

  • 之前给大家看到了, 我们可以在类外面, 直接使用对象调用实例属性, 既然可以调用, 就肯定可以修改, 但是这违反了类的封装原则, 因为对象的状态对于类外部应该是不可访问的.
  • 为了更好的保存属性安全,即不能随意修改,一般的处理方式为: 将属性定义为私有属性
  • 它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。
class Cat(object):
	"""定义一个Cat类"""
	def __init__(self, name, age, color='白色'):
		self.__name = name # 将实例属性变成私有的了
		self.__age = age # 将实例属性变成私有的了
		self.color = color # 公有属性
	def sleep(self): # 实例方法. 公有的
		"""猫咪被命令睡觉"""
		print('%d 岁的 %s猫 正在沙发上睡懒觉' % 		(self.__age, self.__name))
	def eat(self, food): # 实例方法
		"""猫咪被命令吃东西"""
		self.food = food
		print('%d 岁的 %s猫 在吃 %s' % (self.__age, self.__name, self.food))
		def __run(self):
		"""猫咪被命令散步"""
		print('%d 岁的 %s猫 正在散步' % (self.__age, self.__name))
# 实例化对象

其实都是伪私有

# 实例化上面的类
cat = cat('Tom', 3)
print(cat._Cat__name) # 访问私有属性
print(cat._Cat__run) # 访问私有方法

如果就是想要访问私有属性和私有方法, 也是有办法的, 只需要在私有属性或者私有方法前面加一个下划线和类名就可以了 _类名

继承

继承的定义

  • 继承的概念:子类 拥有 父类 的所有 方法 和 属性
  • 面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类
  • 的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展, 实现代码的重用, 相同的
  • 代码不需要重复的编写(可以提高开发的效率)
  • 通过继承创建的新类称为“子类”或“派生类”。
  • 被继承的类称为“基类”、“父类”或“超类”。
class Father(object):
	def __init__(self, name='马云', age=50):
		self.__name = name # 私有属性
		self.age = age # 公有属性
	def __test(self): # 私有方法
		print(self.__name) # 打印私有属性
		print(self.age)
	def test(self):
		print(self.__name) # 打印私有属性
		print(self.age)
class Son(Father):
	def demo1(self):
		# print(self.__name) #不能访问到父类的私有属性
		print(self.age)
	def demo2(self):
		# self.__test() #不能访问父类中的私有方法
		self.test()
		
ft = Father()
# print(ft.__name) #程序出现异常,不能访问私有属性
print(ft.age)
# ft.__test() #程序出现异常,不能访问私有方法
ft.test()
print("------分割线-----")
son = Son(name="小张", age=18)
son.demo1()
son.demo2()

私有的属性,不能通过对象直接访问,但是可以通过方法访问
私有的方法,不能通过对象直接访问,但是可以通过方法访问
私有的属性、方法,不会被子类继承,也不能被访问
一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用

多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法

class Children(Father, Son):

Python 中的 mro —— 方法搜索顺序
Python 中针对 类 提供了一个 内置属性 mro 可以查看 方法 搜索顺序
mro 是 method resolution order ,主要用于 在多继承时判断 方法、属性 的调用
路径
在搜索方法时,是按照 mro 的输出结果 从左至右 的顺序查找的
如果在当前类中 找到方法,就直接执行,不再搜索
如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
如果找到最后一个类,还没有找到方法,程序报错
提示:开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存在 同名的属性或
者方法,应该 尽量避免 使用多继承

重写父类

当 父类 的方法实现不能满足子类需求时,可以对方法进行 重写
所谓 重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的
方法

  • 覆盖 父类的方法
    具体的实现方式,就相当于在 子类中 定义了一个 和父类同名的方法并且实现, 直接写想实现
    功能的代码
  • 对父类方法进行 扩展
  • 在需要的位置使用 super().父类方法 来调用父类方法的执行( 或者父类名().父类方法, 不推
    荐 )
    代码其他的位置针对子类的需求,编写 子类特有的代码实现
class A(object):
	def test(self):
	print('原有的功能代码')
class B(A):
	def test(self):
	super().test() # 扩展型重写
	print('新的功能代码')
	
	
b = B()
b.test()
posted @ 2024-11-19 17:45  云昔子  阅读(2)  评论(0编辑  收藏  举报