4.类

函数式编程

面向过程编程

面向对象编程:类、实例

一、类定义

1.定义

class Cat(Cat_Dad):				# class 类名(父类):
# 大驼峰命名法:每个单词的首字母大写
	'''
	这是一个猫类
	'''
	pass

2.概念

  • 类(Class): 用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法,其中的对象被称作类的实例。是一个独立存放变量(属性/方法)的空间(类只能访问类属性)
  • 实例:也称对象。通过类定义的初始化方法,赋予具体的值,成为一个真实的物体。每个实例都是一个独立的变量空间,不同实例之间的空间互相不可见(修改某一实例的类属性时,不影响其他实例)
  • 实例化:创建类的实例的过程或操作
  • 数据成员:实例变量、类变量、方法、类方法、静态方法和属性等的统称
  • 实例变量:定义在实例中的变量,只作用于当前实例
  • 类变量:类变量是所有实例公有的变量。类变量定义在类中,但在方法体之外
  • 方法:类中定义的函数
  • 类方法:类方法是将类本身作为对象进行操作的方法
  • 静态方法:不需要实例化就可以由类执行的方法
  • 属性:通过实例可以访问的变量。类中每个属性都必须有初始值
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对父类的方法进行改写,这个过程也称override
  • 封装:将内部实现包裹起来,对外透明,提供api接口进行调用的机制
  • 继承:即一个派生类(derived class)继承父类(base class)的变量和方法
  • 多态:根据对象类型的不同以不同的方式进行处理
  • 运算符“.”:用于进行变量空间的运算,通过 . (点)运算符来调用类中封装好的对象

二、 属性

一个“实例”的“特征”,就是“属性”, 例如:color,eat就是我们kitty和hua对象的属性

通过句点法给实例赋值

kitty.color = "white"
kitty.eat = "milk"
hua.color = "colorful"
hua.eat = "fish"

1.实例属性:记录的是每一个实例的特征

class Cat:
	'''
	这是一个猫类
	'''
    
	def __init__(self, color, eat):		# init两边分别两个下划线
		self.color = color			# 实例属性
		self.eat = eat
     
kitty = Cat("white", "milk")
print(kitty.color)	# white

#self 指的是实例对象

#color, eat 指的是实例属性

2.类属性:记录与类相关的特征

定义在类中,方法之外的变量,称作类属性

类属性是所有实例公有的变量,每一个实例都可以访问、修改类属性

class Cat:
	count = 0				# 类属性,记录你实例化对象的数量
	def __init__(self, color, eat):
		self.color = color			# 实例属性
		self.eat = eat
		Cat.count += 1			# 内部调用:类名.类属性

kitty = Cat("white", "milk")
hua = Cat("colorful", "fish")
lucky = Cat("black", "food")

#类属性外部调用
print(Cat.count)		# 外部调用1:类名.类属性
print(kitty.count)		# 外部调用2:实例名.类属性
print(kitty.color)		# 实例调用实例属性
#print(Cat.color)		# 类是不能调用实例属性

3.私有属性

  • 属性前加单下划线_:告诉别人这是私有的,但依然可以使用
  • 属性前加双下划线__:只能在类的内部访问,外部不能使用,但可以蛮横的从外部访问
  • 在 Python 中, _ 和 __ 的使用 更多的是一种规范/约定,没有真正限制的目的定义在类中的私有属性也可以被子类继承
(1).用于成员保护和访问限制
class Cat:
    def __init__(self, color, eat, old):
        self.color = color		# 实例属性
        self._eat = eat			# 外部可访问的私有属性
        self.__old = old			# 外部不可以访问的私有属性

kitty = Cat("white", "milk", "5")
print(kitty.color)		# white
print(kitty._eat)		# milk
# print(kitty.__old)	# AttributeError: 'Cat' object has no attribute '__old'
(2).外部访问和修改私有属性
class Cat:
    def __init__(self, color, eat, old):
        self.color = color  # 实例属性
        self._eat = eat  # 外部可访问的私有属性
        self.__old = old  # 外部不可以访问的私有属性

    def get_old(self):		# 访问私有属性方法
        return self.__old

    def set_old(self, old):		# 修改私有属性方法
        self.__old = old

kitty = Cat("white", "milk", "5")
print(kitty.get_old())  # 5
kitty.set_old(6)
print(kitty.get_old())  # 6
(3).拓展
class Cat:
    def __init__(self, color, eat, old):
        self.color = color  # 实例属性
        self._eat = eat  # 外部可访问的私有属性
        self.__old = old  # 外部不可以访问的私有属性

    def get_old(self):		# 访问私有属性方法
        return self.__old

    def set_old(self, old):		# 修改私有属性方法
        self.__old = old
   
kitty = Cat("white", "milk", "5")
kitty.__old = 6		# 注意:此处并没修改私有属性,而是新建了个叫__old的类属性,所以私有属性值并未改变
print(kitty.get_old())  # 5		# 私有属性
print(kitty.__old)	# 6		# 新建的类属性

三、方法

1.实例方法

  • 方法总是定义在类中的,但是却叫“实例方法”,因为它表示该类所有实例所共有的行为

  • 通常,将默认会传入的那个参数命名为self,用来表示调用这个方法的实例对象本身

  • self:传入的是创建的对象,self可以直接将对象的属性传入到方法中

class Cat:
    """
    这是一个猫类
    """

    def add_cat(self):
        print("{}__{}".format(self.color, self.eat))

kitty = Cat()
kitty.color = "white"
kitty.eat = "milk"
# 函数调用1
Cat.add_cat(kitty)  # 类.方法(实例,参数)
# 函数调用2
kitty.add_cat()  # 实例.方法(参数)
*********************************************************************
white__milk
white__milk

2.类方法

见描述器与装饰器

3.私有方法

私有方法:不可以被实例和类直接调用,可在函数内部被调用,用于成员保护和访问限制

class Cat:
	"""
	这是一个猫类
	"""
	count = 0
	def __init__(self, name, color, eat):
		self.name = name			# 实例属性
		self._color = color			# 外部可访问的私有属性
		self.__eat = eat			# 外部不可以访问的私有属性
		Cat.count += 1

	def __print_cat(self):					# 私有方法
		return "我是私有方法"

	def add_cat(self):
		print("{}__{}__{}".format(self.name, self._color, self.__eat))
		print(self.__print_cat())

        
kitty = Cat("kitty", "white", "milk")
Cat.add_cat(kitty)					
kitty.add_cat()						
# 私有方法:不可以被实例和类直接调用
# kitty.__print_cat()
# Cat.__print_cat()
*********************************************************************
kitty__white__milk
我是私有方法
kitty__white__milk
我是私有方法

四、封装

封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现,外界只能通过接口使用该对象,而不能通过任何形式修改对象内部实现,类通过将函数和变量封装在内部,实现了比函数更高一级的封装

class Cat:
	'''
	这是一个猫类
	'''
	count = 0				
	def __init__(self, color, eat):
		self.color = color			
		self.eat = eat
		
	def add_cat(self):
		print("{}__{}".format(self.color, self.eat))
		
# 错误调用(类将它内部的变量和方法封装起来,阻止外部的直接访问)	
# print(count)
# add_cat()

五、继承、多继承

1.概念

  • 一个类继承另一个类时,它将自动获得另一个类的所有属性和方法

  • 原有的类称为父类,新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法

  • 继承的意义是:重用代码,方便代码的管理和修改

  • 继承不是变量空间的复制

2.优先级

  • 当继承多个父类时,如果父类中有相同的方法,那么子类会优先使用最先被继承的方法

  • 类在生成时会自动生成方法解析顺序,可以通过 类名.mro()来查看

(1)
class A:
	def f(self):
		print("A")

class B:
	def f(self):
		print("B")

class C(A):
	def f(self):
		print("C")

class D(B):
	def f(self):
		print("D")

class E(C, D):
	def f(self):
		print("E")

s = E()			# 实例化对象
s.f()			# 调用方法,self始终指向的是实例对象e,所以方法选择的优先级始终从E类开始
## 优先级	E——>C——>A——>D——>B
print(E.mro())
*********************************************************************
[<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class 'object'>]
(2)
class F:
	def f(self):
		print("F")

class A(F):
	def f(self):
		print("A")

class B(F):
	def f(self):
		print("B")

class C(A):
	def f(self):
		print("C")

class D(B):
	def f(self):
		print("D")

class E(C, D):
	def f(self):
		print("E")

s = E()			# 实例化对象
s.f()			# 调用方法,self始终指向的是实例对象e,所以方法选择的优先级始终从E类开始
## 优先级	E——>C——>A——>D——>B——>F

3.构造方法

  • 子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找
  • 根据父类定义中的顺序,以深度优先的方式逐一查找父类

4.重写

当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法,为此,可在子类中定义一个与要重写的父类方法同名的方法,这样,Python不会考虑父类方法,只关注子类中定义的相关方法

重写后,继续使用父类中的方法的办法
(1) .方法一(不灵活)
class A():
	def f(self):
		print("A")

class B():
	def f(self):
		print("B")

class C(A, B):
	def f(self):
		print("C")
		A.f(self)			# 调用A.f()
			
c = C()
c.f()						
*********************************************************************
C
A
(2).super().方法名
class A():
	def f(self):
		print("A")

class B():
	def f(self):
		print("B")

class C(A, B):
	def f(self):
		print("C")
		super().f()			# super().方法名

c = C()
c.f()						
*********************************************************************
C
A

5.object基类

object是所有类的父类

6.Mix-in设计模式

“Mix-in类”是继承的终点,多继承就一层,且是最后一层

例如:人(子类)——>胳膊、腿、头、身体(父类)

六、多态

动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用,这就是多态

class Cat:
    def kind(self):
        print("i am a cat")

        
def show_kind(animal):
    animal.kind()
    
c = Cat()
show_kind(c)  # i am a cat

七、魔术方法

魔术方法,给了我们一个自定义的接口,函数执行的底层其实就是去调用了魔术方法,我们只需要修改对应的魔术方法,即可实现自定义

1.运算符方法

__add__(self,other)	# x+y
__sub__(self,other)	# x-y
__mul__(self,other)	# x*y
__mod__(self,other)	# x%y
__iadd__(self,other)	# x+=y
__isub__(self,other)	# x-=y
__radd__(self,other)	# y+x
__rsub__(self,other)	# y-x
__imul__(self,other)	# x*=y
__imod__(self,other)	# x%=y

class Rectangle:

    def __init__(self,length,width):
        self.length = length
        self.width  = width

    def area(self):
        areas = self.length * self.width
        return areas

    def __add__(self, other):
        add_length = self.length + other.length
        add_width  = self.width + other.width
        return add_length,add_width


a = Rectangle(3, 4)
b = Rectangle(5, 6)
print(a + b)	# (8, 10)

2.__init__()

实例化方法,通过类创建实例时,自动触发执行。初始化实例属性

__init__的参数传递过程:实例化产生一个类的实例——>Python自动调用 实例.__init__(参数)——>转换为类.__init__(实例,参数)

3.__str__()__repr__()

正常情况下,直接打印类,输出类的地址

为一个类中定义了__str__()方法,那么在打印对象时,默认输出__str()__的返回值

class A:
	def __str__(self):
		return "str"

	def __repr__(self):
		return "repr"

a = A()
print(a)	# str
*********************************************************************
# 把类的实例变成一个字符串,__str__
# __str__:返回的必须是字符串,对用户友好,适合print输出
# __repr__:__str__备胎,如果有__str__,print会先执行__str__

在python中,str和repr方法在处理对象的时候,分别调用的是对象的 __str____repr__方法

print也是如此,调用str函数来处理输出的对象,如果对象没有定义__str__方法,则调用repr处理

在 shell 模式下,展示对象 __repr__的返回值

str:尽可能的提供简洁且有用的信息,让用户尽可能吸收到必要的信息
repr:尽可能向开发者提供创建该对象时的必要信息,让开发者可以直接通过复制粘贴来重建对象

4.__call__()

正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要定义__call__方法

为一个类编写了call方法,那么在该类的实例后面加括号,会调用这个方法,即:对象() 或者 类()()

(1).正常情况
class A:
   def __init__(self, num):
      self.num = num

a = A(33)
a()		# TypeError: 'A' object is not callable
(2).call方法
class A:
	def __init__(self, num):
		self.num = num

	def __call__(self):
		print("call")

a = A(33)
a()		# call
A(33)()     # call

5.查看

__module__  # 查看模块名
__class__	# 查看类名
__base__	# 查看继承的父类
__bases__	# 查看继承的全部父类
__dict__	# 查看全部属性,返回属性和属性值键值对形式
__doc__		# 查看对象文档,即类中的注释(用引号注视的部分)
__dir__		# 查看全部属性和方法

class A:
	"""
	这是一个类
	"""

	def __init__(self, num):
		self.num = num

a = A(33)
print(a.__class__)
print(a.__dict__)
print(a.__doc__)
*********************************************************************
<class '__main__.A'>
{'num': 33}
	这是一个类

6.__getattr__()__setattr__()__delattr__()

见描述器与装饰器

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值