类,继承

  • 类(class):用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法,对象是类的实例
  • 类是一个独立存放变量(属性,方法)的空间,它定义了该集合中每个对象共有的属性和方法
  • 类由类名,属性(变量),方法(函数)组成,类名约定俗成用大驼峰
  • 对象:通过类定义的数据结构实例,对象包括两个数据成员:变量(类变量和实例变量)和方法,对象是类的实例化
  • 方法:类中定义的函数
  • 变量在类中称为属性,但是类中的属性不仅仅只包含变量,函数等其他的对象也可以作为类的属性
  • 类变量:类变量在整个实例化的对象中是共用的,类变量定义在类中且在函数体之外
  • 函数是代码块的封装,类是函数的封装
  • 类是一类事物的抽象,不是真是存在的,描绘了该类事物的共性

实例

  • 实例变量:定义在方法中的变量,只作用于当前实例的类
  • 实例化:创建一个类的实例,类的具体对象,对象是类的实例化
  • 实例也是一个独立存放变量的空间,每一个实例都是一个独立的变量空间,不同实例之间的空间互相不可见

类创建

  • 创建类:使用class语句来创建一个新类,class之后为类的名称并以冒号结尾:
  • 定义在类里面,函数外面的变量是类全局
  • 优先访问实例属性,再访问类属性
  • 类属性:共性,实例属性:特性

案例1:

class Person(object):   #定义类
#class Preson(object):	和class Person:一样
   		var1 = "直接封装在类中的变量" 		#类变量/属性
print(Person.var1)
Person.var2 = "后来封装在类中的变量"    #在类外添加类属性
print(Person.var2)
p = Person()    #类的实例化,相对于函数叫调用
a = p.var1
print(a)   #类属性访问
print(p.var2)		

案例2:

class Person(object):   
    pass
p1 = Person()
p2 = Person()
p1.var = "在实例中封装的变量"	#对象添加的属性,它的空间是独立的
							#实例属性,类和其他的实例访问不到
print(p1.var)
~~print(Person.var)~~     #类中找不到,不会去找实例中的
~~print(p2.var)~~ 	#p2没有,去找Person也没有
  • 类里面函数之外的变量都称之为类属性,类里面的其他方法也可以访问
  • 没加self的变量(并在函数里面)是普通变量,类里面其他函数访问不了
class Person(object):
    def a(self):		#加了self的,实例化成对象可用,不实例化不可用
        print("hahaha")
    def b():		#不加self的是类属性,实例化的对象不能调用,类可以直接调用
        print("xixixi")
p = Person()
p.a()	#Person.a()是错误的
Person.b()	#p.b()是错误的

类的方法

  • 实例本身就拥有的数据,要访问这些数据没必要从外面的函数去访问,可以直接在类的内部定义访问数据的函数,这样就把数据给封装起来了,这些封装数据的函数和类本身是关联起来的,我们称之为类的方法
  • 通常,将默认会传入的那个参数命名为self,用来表示调用这个方法的实例对象本身
  • 要定义一个方法,除了第一个参数是self外,其他和普通函数一样,要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入
  • 封装的另一个好处是可以给类增加新的方法
  • 案例1:
class Person(object):		
    	def eat(self):		#实例方法,实例可调用,类不可调用
        	print("{} is eating".format(self.name))
p1 = Person()	#没有定义参数,不传参
p1.name = "xiaoming"
p2 = Person()
p2.name = "xiaohong"
p1.eat()	#xiaoming is eating
p2.eat()	# xiaohong is eating
  • 在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
  • 当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
  • 案例2:
class Person(object):
    def __init__(self,name):		#对类Person定义了参数
        self.name = name
    def __str__(self):	
        return 'woshi%s' % self.name		#打印类的调用时起作用
    def eat(self):  # 实例方法,实例可调用
        print("{} is eating".format(self.name))
p = Person('xiaoming')
p1 = Person('xiaohong')
p1.eat()  # xiaohong is eating
print(p)		#woshixiaoming		
  • def init(self): #初始化函数
class Man(object):
    def __init__(self,name,sex):
        self.name = name	#类属性
        self.sex = sex		#类属性
        print("%s是个%s出生落地了" % (self.name,self.sex))
    def cry(self):
        print("%s哭了" % (self.name))
    def laugh(self):
        print("%s笑了" % self.name)
man = Man("xiaoli","girl")
man.cry()
#xiaoli是个girl出生落地了
 xiaoli哭了
  • 类里面凡是加了self的变量都称为类属性,className.属性名,类里面的其他方法也是可以访问的
  • 函数里面没加self的就是普通变量,类里面其他函数访问不了
  • 定义在类里面函数外面的变量,是类全局,函数都能调用
  • 实例化对象既能访问实例属性,也能访问类属性
  • 例子1
class Dog:

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

	def call(self):
		print(self.color)
		print('wang')

	def change_color(self,new_color):
		print(self.color)
		self.color = new_color
		return f'new color is {self.color}'

wangcai = Dog('hei')
print(wangcai.color)
wangcai.color = 'bai'
print(wangcai.color)
wangcai.call()
print(Dog('bai').change_color('hong'))
#hei

 bai
 
 bai
 wang
 
 bai
 new color is hong

self可以理解为实例化出来的对象,self.color相当于wangcai.color

  • 例子2
class Dog:

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

	def call(self):
		print(self.color)
		print('wang')

	def change_color(self,new_color):
		print(self.color)
		self.color = new_color
		print('new color is %s' % self.color)

def test(name):	
	name.change_color('green')

wangcai = Dog('hei')
print(wangcai.color)
wangcai.color = 'bai'
print(wangcai.color)
wangcai.call()
Dog('bai').change_color('hong')
a = test(wangcai)		#参数是实例化的对象wangcai
#hei

 bai
 
 bai
 wang
 
 bai
 new color is hong
 
 bai
 new color is green
class Home:

	def __init__(self,area):
		self.area = area
		self.containsItem = []	#用于保存对象

	def __str__(self):
		msg = '家当前可用面积为:' + str(self.area) + '\n'
		# if len(self.containsItem ) > 0:
		msg += '家里的物品有:'
		if len(self.containsItem) > 0:
			for temp in self.containsItem:
				msg += temp.name + ','
			# break
			msg = msg[:-1]
		else:
			msg += '没有任何东西'

		return msg

	def add_item(self,item):

		if self.area > item.area:
			self.containsItem.append(item)

		self.area -= item.area


class Bed:

	def __init__(self,name, area):
		self.name = name
		self.area = area

	def __str__(self):
		msg = self.name + '床的面积为:' + str(self.area)

		return msg

home = Home(128)
print(home)
bed = Bed('席梦思',4)
print(bed)
home.add_item(bed)
print(home)
bed2 = Bed('硬板床',3)
print(bed2)
home.add_item(bed2)
print(home)
#家当前可用面积为:128
 家里的物品有:没有任何东西
 席梦思床的面积为:4
 家当前可用面积为:124
 家里的物品有:席梦思
 硬板床床的面积为:3
 家当前可用面积为:121
 家里的物品有:席梦思,硬板床

骰子游戏

import random


class Game(object):
	"""
	骰子游戏
	"""
	def __init__(self,player1,player2):
		self.player1 = player1
		self.player2 = player2
		print('游戏初始化成功,可以开始')

	def start_game(self):
		self.player1.cast()
		self.player2.cast()
		print(self.player1)
		print(self.player2)


class Player(object):
	"""
	玩家信息和玩的动作
	"""
	def __init__(self,name,sex,*dice):
		self.name = name
		self.sex = sex
		self.dices = dice	#表示该玩家拥有的骰子元组

	def cast(self):
		"""
		玩家的行为动作,摇骰子
		:return:
		"""
		for dice in self.dices:
			dice.move()

	def guess_dice(self):
		"""
		猜点数,猜多少个多少点
		:return:
		"""
		return (4,2)	#4个2

	def __str__(self):
		play_dice_count_list = [self.dices[0].count, self.dices[1].count, self.dices[2].count]

		return '%s摇的骰子点数是%s' %  (self.name,str(play_dice_count_list))


class Dice(object):
	"""
	骰子
	"""
	def __init__(self):
		"""
		骰子点数
		:param count:
		"""
		self.count = 0

	def move(self):
		"""
		投的骰子的点数
		:return:
		"""
		self.count = random.randint(1,6)	#对应自己的职责,骰子就是生成一个数,统计点数的个数是玩家去算,不归骰子管

#游戏开始之前准备六颗骰子
d1 = Dice()
d2 = Dice()
d3 = Dice()
d4 = Dice()
d5 = Dice()
d6 = Dice()

#每次游戏需要两位玩家
p1 = Player('xiaoge','man',d1,d2,d3)
p2 = Player('na','girl',d4,d5,d6)

#一共玩五次游戏
for i in range(1,6):
	print('第%d次游戏的情况------' % i)
	game = Game(p1,p2)
	game.start_game()

#第1次游戏的情况------
 游戏初始化成功,可以开始
 xiaoge摇的骰子点数是[4, 6, 3]
 na摇的骰子点数是[5, 1, 5]
 第2次游戏的情况------
 游戏初始化成功,可以开始
 xiaoge摇的骰子点数是[2, 3, 2]
 na摇的骰子点数是[6, 4, 4]
 第3次游戏的情况------
 游戏初始化成功,可以开始
 xiaoge摇的骰子点数是[1, 6, 3]
 na摇的骰子点数是[5, 5, 5]
 第4次游戏的情况------
 游戏初始化成功,可以开始
 xiaoge摇的骰子点数是[4, 2, 2]
 na摇的骰子点数是[6, 4, 3]
 第5次游戏的情况------
 游戏初始化成功,可以开始
 xiaoge摇的骰子点数是[6, 1, 6]
 na摇的骰子点数是[4, 2, 2]

私有属性

-私有属性属于这个类,一般不要外面调用,保护起来
-Python中私有属性有两种,一个下划线_和两个下划线__
- 以一个下划线_开头,私有属性,可以在外面调用,约定俗成不在外面调用,不常用
- 以两个下划线__开头,强制私有属性,在外面调用不了,比一个下划线常用

  • 案例
class User(object):

	def __init__(self):
		self.__password = '234232'#隐藏属性
		print('%s' % self.__password)

	def change_password(self,pw):
		self.__password = pw
		return '%s' % self.__password
u1 = User()

print(u1.change_password('666666'))
print(u1.__password)	#此方法是错误的,私有属性在外面没法调用,但在类里面可以调用更改

#Traceback (most recent call last):
  File "/home/xiaoge/web_prv/text.py", line 209, in <module>
    print(u1.__password)
 234232
 AttributeError: 'User' object has no attribute '__password'
 666666

继承

class A(object):
	def play(self):
		print("xixi")
class B(A):
	pass
  • 类继承:类的继承可以让子类将父类的全部方法和类属性继承过来(私有属性除外),在Python3中,默认继承object类

实例(类属性,类方法,静态方法)

  • 例1
#class Woman(object):
class Woman(object):		#效果同上行代码
	face = 'beautiful'		#类属性
	def cry(self):
		print("xiaoli哭了")
	def laugh(self):
		print("%s笑了" % self.name)
	@classmethod	#类方法一定要在方法上面加一个装饰器,类方法的参数woman代表当前的类
	def change_face(cls):		#约定俗成用cls,和上面约定俗成用self一样
		cls.face = 'fun'	#woman代表当前的类,所以可以更改类属性
	@staticmethod	#静态方法,也属于类,没有默认传递的参数,如果定义参数,调用时一定要传参,可以通过类对象,类调用
	def test():
		Woman.face = 'funny'	#通过类名调用修改类属性
		print('静态方法')


class Child(Woman):
	def smile(self):
		print("笑了")
		self.cry()
print(Child.face)		#beautiful		#Child继承Woman的类属性face,可以直接通过类来访问,也可以通过类的对象来访问
child = Child()
child.cry()				#xiaoli哭了
child.smile()			#笑了
					     xiaoli哭了	#因为self调用了cry()方法	self.cry()
print(child.face)	#beautiful		#通过类的对象访问父类的类属性
child.face = 'beautifuller'	#类属性要通过类修改,对象没法修改类属性,只是定义了一个对象属性name并赋值
print(child.face)		#beautifuller
print(Child.face)		#beautiful		#通过类查看类属性发现类属性没被对象修改
Child.face = 'nice'
print(Child.face)		#nice		#子类只能修改自己的类属性,不能修改父类的类属性
print(Woman.face)		#beautiful
print(child.face)		#beautifuller
Woman.change_face()
print(Woman.face)		#fun
Child.change_face()	#类方法也可以被继承
print(Child.face)		#fun
  • 例2
class Animal(object):	#父类

	def __init__(self):
		self.name = 'animal'
		self.__name = 'animal0'
	def eat(self):
		print('吃')

	def sleep(self):
		print('睡')


class Dog(Animal):	#Animal的子类

	def __init__(self,name):		#父类和子类都有的方法,子类优先调用自己的方法
		self.name = name

	def call(self):
		print('汪汪叫')


class Cat(Animal):	#Animal的子类

	# def __init__(self):		#如果对Cat进行初始化,Cat就调用自己的__init__,不会继承Animal的__init__方法,就会报错AttributeError: 'Cat' object has no attribute 'name',此处仍是方法的继承,不是属性的调用
	# 	print('猫初始化了')
	def catch(self):
		print('抓老鼠')

class BoSiMao(Cat):

	def meng(self):
		print('卖萌')
		
wangcai = Dog('wangcai')	#wangcai有三个功能,吃睡叫
wangcai.eat()	#吃
print(wangcai.name)	#wangcai
miao = Cat()	#miao有三个功能,吃睡抓
print(miao.name)		#animal
print(wangcai.__name)		#AttributeError: 'Dog' object has no attribute '__name'
print(miao.__name)		#AttributeError: 'Cat' object has no attribute '__name'
xiaomiao = BoSiMao()
print(xiaomiao.name)		#animal		#继承父类的父类的方法	此处类似多继承,也继承Cat也继承Animal

多继承

  • 当继承多个父类时,如果父类中有相同的方法,那么子类会优先使用最先被继承的方法(第一个父类的)
  • 当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法
class A(object):

	def test(self):
		print('A')


class B(object):

	def test(self):
		print('B')


class C(A,B):
#class C(B,A):		#如果这样写,B的优先级高于A

	def test(self):		#重写
		print('C')

c = C()
c.test()
print(C.__mro__)		#查看C的继承的优先级

#C
 (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

重写:

  • 当子类重写父类方法之后,子类如果有想再次调用父类的方法,可以使用这两种方法:
    • 方法一:
class C(A,B):
	def play(self):
		A.play(self)
		print("这是C")
  • 方法二:
class C(A,B):
	def play(self):
		super().play()
		print("这是C")

super方法

  • super函数可以调用父类的方法
  • 在父类中也使用super函数后,可以通过调用类的mro方法属性来查看继承关系
  • super函数可以来调用父类的方法,使用super的好处在于即使使用父类改变了,那么也不需要更改类中的代码
  • 官方推荐super的用法如示例所示
  • 在Python3中,类被创建时会自动创建方法解析顺序mro,可以通过类名.mro()来查看
  • object是所有类的父类
  • Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx

案例:

class XiaoMing(object):

    def __init__(self):
        self.height = 174
        self.age = 48
        self.money = 1000000000
        
    def health(self):
        print("身体非常好")
        
    def money(self):
        print("小明会赚钱")


class XiaoHong(object):

    def __init__(self):
        self.height = 160
        self.age = 28
        self.money = 100000
        
    def appearance(self):
        print("特别好看")


class XiaoQiang(XiaoMing,XiaoHong):

    def __init__(self):
        self.age = 2

    def study(self):
        print("小强学习好")
        
    def money(self):
        XiaoMing.money(self)
        super().money()
        print("小强会花钱")
        
son = XiaoQiang()
son.health()		#身体非常好
son.appearance()	#特别好看
son.study()	#小强学习好
print(son.age)		#2
print(XiaoMing().age)   #实例化,48
son.money()	#小明会赚钱
			 小明会赚钱
			 小强会花钱
print(XiaoQiang.__mro__)				
 #(<class '__main__.XiaoQiang'>, <class '__main__.XiaoMing'>, <class '__main__.XiaoHong'>, <class 'object'>)		

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值