是用代码组织的更高级别的类,是对对象特征的属性和代表对象的操作方法进行使用。python语言中一切皆对象!
在程序设计中如果 a 代表对象,b 代表对象的属性,c 代表对象的操作方法
在使用对象属性是可用a.b进行调用;使用对象方法时可用a.c()进行调用。
1.类的封装
2.私有属性和私有方法
3.类的继承
4.多态
5.类属性和类方法
6.斗地主发牌程序
1.类的声明:在使用对象时先创建类
class Person: #class为保留字直接使用,Person为定义的类名(每个单词的首字母大写,大驼峰命名法)
2.先设置属性:
设置属性时,不知什么初值,可设为None,这里使用初始化内部定义属性的方法
类的属性可以说成是事物具有的特征,比如说“人”这个类具有的特征:姓名、身高、体重、性别,再比如“房子”这一类具有的特征:面积、风格样式等。
方法1:def _init_(self): #利用内置_init_初始化函数直接对名字,性别赋值(内置的函数还有其它类型)
self.name = "zhangfei"
self.sex = "1"
...
方法2:def _init_(self,name,sex = '男',其它参数):#以name,sex为参数示范,参数的设置是为了创建对象时赋属性值
self.name = name #将name属性返回内置_init_初始化函数,对象被初始化时被自动调用
self.sex = sex #同上,也可以创建一个默认值,不创建时用默认值,创建时sex为创建时的值
...
3.再定义方法:
面向对象编程之所以适合较大程序编写,是因为里面可以封装多个方法,通过类创建对象,来调用对象里面的方法;这里的方法可以说成是行为,比如定义的Person(人)这个类,吃饭,睡觉,喝水都可以是一个行为,当然这个行为根据需求可自定义的
方法创建:def eat(self):
print(""我是{}吃饱了".format(self.name)) #当创建的对象调用eat方法时会执行里面的语句
def sleep(self):
return "{}睡觉了".format(self.name)#当创建的对象调用sleep方法时会执行里面的语句
4.最后创建对象:
所谓的创建对象可以理解为将创建的类名赋值给一个变量,这个变量就是对象;
1.使用方法1创建属性时:
person = Person() #person就是所创建的对象,方法一已经对属性进行初始化,这里不许再进行赋值
2.使用方法2创建属性时:
person = Person("zhangfei","男")#person就是所创建的对象,由于方法二为初始化属性,所以创建对象时对属性进行初始化
4.调用对象里面的方法:
person.eat() #person是创建的对象,eat()是创建类里面的方法,可以直接调用
person.sleep()
5.调用对象里面的方法:
person.eat() #person是创建的对象,eat()是创建类里面的方法,可以直接调用
person.sleep()
class Person:
def __init__(self,name,sex="nan"):
self.name = name
self.sex = sex
def eat(self):
print("我是{}我吃饱了".format(self.name))
def sleep(self):
return "我是{}我睡觉了".format(self.name)
person = Person("张飞","男")
person.eat()
print(person.sleep())
输出结果:
我是张飞我吃饱了
我是张飞我睡觉了
以上是类的封装5步操作方法,但这些仅仅是基本!
什么是私有属性、私有方法??
在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到
私有属性 就是 对象 不希望公开的 属性
私有方法 就是 对象 不希望公开的 方法
怎么定义??
在 定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有 属性或方法
class Person:
def __init__(self,name,sex="nan"):
self.name = name
self.sex = sex
self.__age= 18 #私有属性
self.__weight = 200 #私有属性
def eat(self):
print("我是{}我吃饱了".format(self.name))
def sleep(self):
return "我是{}我睡觉了".format(self.name)
def __money(self):
return "{}有一个亿"。format(self.name) #不想让你知道他有一个亿
person = Person("小花")
print(person.eat()) #可以打印出来
print(person.age()) #私有属性无法打印
print(person.money()) #私有方法无法打印
什么是类的继承??
类的继承就是子类继承父类的属性和方法,并可以通过子类的对象进行访问,从而实现代码的复用。
一,单继承:
从一个父类中调用其属性或方法
class Animal: #动物类
def __init__(self,name):
self.name = name
def eat(self):
print("{}在吃饭".format(self.name))
def sleep(self):
print("{}在睡觉".format(self.name))
class Dog(Animal): #单继承方式,如果父类的方法是子类正好需要的则不需要在进行方法定义
def drink(self):
print("{}在喝水".format(self.name))
def sleep(self):#当父类的方法不适用时可以重定义与父类相同的方法覆盖
print("{}睡懵逼了".format(self.name))
Dog = Dog("狗狗") #调用父类的_init_方法赋予属性
Dog.eat() #调用父类的eat方法
Dog.sleep() #访问自身的sleep方法
Dog.drink() #访问自身的drink方法
输出:
狗狗在吃饭
狗狗睡懵逼了
狗狗在喝水
二、多继承
从两个或两个以上的父类调用其属性或方法
#Animal类
class Animal:
str = "灵姐" #为类方法定义的类属性
def __init__(self,name):
self.name = name
def eat(self):
print("{}在吃饭".format(self.name))
def sleep(self):
print("{}在睡觉".format(self.name))
print("{}睡了".format(self.name))
#Person类
class Person:
def __init__(self,name):
self.name = name
def run(self):
print("{}在跑步".format(self.name))
#Dog类
class Dog(Animal,Person): #类的继承,多继承,如果父类的方法是子类正好需要的则不需要在进行方法定义
def drink(self):
print("{}在喝水".format(self.name))
def sleep(self):#当父类的方法不适用时可以重定义与父类相同的方法覆盖
super().sleep() #当父类的功能是完成子类功能的一部分是,需要扩展,则使用该语句
print("{}睡懵逼了".format(self.name))
Dog = Dog("狗狗")
Dog.eat() #调用父类Anmail类的eat方法
Dog.sleep() #调用父类Anmail类的sleep方法,以及自身的sleep方法
Dog.drink() #访问自身的drink方法
Dog.run() #调用父类Person类的run方法
输出:
狗狗在睡觉
狗狗睡了
狗狗睡懵逼了
狗狗在喝水
狗狗在跑步
多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果
多态 可以 增加代码的灵活度
以 继承 和 重写父类方法 为前提
是调用方法的技巧,不会影响到类的内部设计
class Dog:
def __init__(self,name):
self.name = name
def play(self):
print("%s在地上玩"%self.name)
class Flydog(Dog):
def play(self):
super().play()
print("{}在天上玩".format(self.name))
class Person:
def __init__(self,name):
self.name = name
def play(self,Dog):
print("{}和{}一块玩".format(self.name,Dog.name))
dog = Dog("哈士奇")
flydog = Flydog("哮天犬")
person = Person("小王")
flydog.play()
person.play(dog)
person.play(flydog)
输出:
哮天犬在地上玩
哮天犬在天上玩
小王和哈士奇一块玩
小王和哮天犬一块玩
结论:
Person 类中只需要让 狗对象 调用 game 方法,而不关心具体是 什么狗
game 方法是在 Dog 父类中定义的
在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果
什么是类属性??
1.类属性 就是给 类本身需要绑定的属性
2.通常用来记录 与这个类相关 的特征
3.类属性 不会用于记录 具体对象的特征
比如:
class Dog:
name = "哈士奇" #类属性
def _init_(self):
pass
什么是实例属性??
根据类创建的实例可以任意绑定属性。
给实例绑定属性的方法是通过实例变量,或者通过self变量
比如:
class Dog:
def _init_(self,name,age):
self.name = name #实例属性
self.age = age #实例属性
dog = Dog("哈士奇",2)
什么是类方法??
类方法 就是针对 类对象 定义的方法
类方法 内部可以直接访问 类属性 或者调用其他的 类方法
类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法
类方法的 第一个参数 应该是 cls
由 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用
这个参数和 实例方法 的第一个参数是 self 类似
使用其他名称也可以,不过习惯使用 cls
通过 类名. 调用 类方法,调用方法时,不需要传递 cls 参数
在方法内部
可以通过 cls. 访问类的属性
也可以通过 cls. 调用其他的类方法
class MyClass: # 定义类
val1 = 'String 1' # 静态变量
def __init__(self,val2):
self.val2 = 'Value 2'
@classmethod # 类方法
def classmd(cls):
print( 'val1:' + cls.val1 + ',无法访问val2的值')
MyClass.classmd() #通过类直接调用
c = MyClass() #创建对象
c.classmd() #在对象里调用
输出:
val1:String 1,无法访问val2的值
val1:String 1,无法访问val2的值
什么是静态方法??
如果需要在 类 中封装一个方法,这个方法:
既 不需要 访问 实例属性 或者调用 实例方法
也 不需要 访问 类属性 或者调用 类方法
这个时候,可以把这个方法封装成一个 静态方法
class MyClass: # 定义类
var1 = 'String 1'
@staticmethod # 静态方法
def staticmd():
print("我是静态方法")
MyClass.staticmd()
c = MyClass()
c.staticmd()
输出:
我是静态方法
我是静态方法
在python从入门到入魔第七天——random库的使用(简单模拟斗地主发牌算法)写了斗地主发牌的程序
这次使用面向对象编程
模拟斗地主洗发牌——3人54张牌,逐个发牌玩法
思路:
1.先准备54张牌并放到一个序列类型中
2.再进行洗牌,由于随机洗牌则可以使用shuffle函数
3.选出地主牌
4.然后发牌则可以用上的循换每个玩家生成17张牌
5.判断地主牌在谁手上
6.输出
import random
class Poke:
poke = []
play1 = []
play2 = []
play3 =[]
last =None
def __init__(self,flowers,nums):
self.flowers = flowers
self.nums = nums
def __str__(self):
return "%s%s"%(self.flowers,self.nums)
#组装牌
@classmethod
def _组装_(cls):
flowers = ["♥","♦","♣","♠"]
nums = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
king = {'big':'大王','small':'小王'}
for flower in flowers:
for num in nums:
cls.poke.append(Poke(flower,num)) #Poke()调用类内的__str__()方法
cls.poke.append(king['big'])
cls.poke.append(king['small'])
print("欢迎来到斗地主游戏".center(100, "-"))
#洗牌
@classmethod
def _洗牌_(cls):
random.shuffle(cls.poke)
#选地主牌
@classmethod
def _地主_(cls):
cls.dd = random.choice(cls.poke)
print("地主牌是:{}".format(cls.dd))
#发牌
@classmethod
def _发牌_(cls):
for i in range(17):
cls.play1.append(cls.poke.pop(0))
cls.play2.append(cls.poke.pop(0))
cls.play3.append(cls.poke.pop(0))
cls.last = list(cls.poke)
#抢地主
@classmethod
def _抢地主_(cls,play):
if cls.dd in play:
print("地主玩家")
for i in cls.last+play:
print(i,end=" ")
else:
for i in play:
print(i,end=" ")
@classmethod
def _print_(cls):
print("玩家1:")
cls._抢地主_(play=cls.play1)
print("\n玩家2:")
cls._抢地主_(play=cls.play2)
print("\n玩家3:")
cls._抢地主_(play=cls.play3)
print("\n底牌:")
for i in cls.last:
print(i,end=" ")
print("\n"+"请开始你们的表演".center(100,"-"))
Poke._组装_()
Poke._洗牌_()
Poke._地主_()
Poke._发牌_()
Poke._print_()
输出结果:
---------------------------------------------欢迎来到斗地主游戏----------------------------------------------
地主牌是:♠5
玩家1:
♣5 ♦4 ♦5 ♦K ♦3 ♠4 ♠K ♠7 ♥8 ♥K ♠6 ♣8 ♥9 ♣6 ♣3 ♦Q ♠2
玩家2:
地主玩家
♥Q ♦7 ♣4 ♣A ♠8 ♦8 ♣10 ♦J ♣J ♠5 ♥2 ♠10 ♥5 ♦9 ♥J ♣7 ♠Q ♠J ♠3 大王
玩家3:
♠9 ♥3 ♥A ♥10 ♥6 ♣9 ♦10 ♥4 ♠A 小王 ♣2 ♦A ♣K ♥7 ♦6 ♦2 ♣Q
底牌:
♥Q ♦7 ♣4
----------------------------------------------请开始你们的表演----------------------------------------------