每个对象都有一个类型,类是创建对象实例的模板,是对对象的概括,它包含对所创建对象的属性描述和行为特征的定义,相当于一个模板。
在创建类时用变量形式表示的对象属性称为数据成员或属性(成员变量),用函数形式表示的对象行为称为成员函数(成员方法),成员属性和成员方法统称为类的成员。
格式:
class 类名:
属性(成员变量)
属性
...
成员函数
# 定义Person类
class Person:
num = 1
def SayHello(self):
print('Hello!')
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
对象是类的实例,定义具体对象后,可以通过“对象名.成员”访问其中的数据成员或成员方法。
对象名 = 类名
p = Person()
p.SayHello()
类有一个名为 _ _ init _ _() 的特殊方法(构造方法,以两个下划线开头和结束),该方法在类实例化时会自动调用。
构造函数一般用于对象数据成员设置初值或进行其他必要的初始化工作。用户未涉及构造函数,Python将会提供一个默认的构造函数。
class Complex:
def __init__(self,realpart,imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0,-4.5) #类实例化,会自动调用 __init__() 方法
print(x.r,x.i)
用来释放对象占用的资源,当对象被销毁的时候自动调用,使用del删除,即对象被销毁
class Complex:
def __init__(self,realpart,imagpart):
self.r = realpart
self.i = imagpart
def __del__(self):
print("Complex不存在")
x = Complex(3.0,-4.5)
print(x.r,x.i)
print(x)
del x
在执行“del x”语句后,系统自动调用析构函数,输出“Complex不存在”
实例属性:在构造函数__init__()中定义的,定义时以self作为前缀;
类属性:在类中(方法之外)定义的属性。
在主程序中(类的外部),实例属性属于实例(对象),只能通过对象名来访问;
类属性属于类,可以通过类名访问,也可以通过对象名访问,为类的所有实例共享。
class Person:
num = 1 #类属性(类变量)
def __init__(self,str,n): #构造方法
self.name = str #实例属性
self.age = n
def SayHello(self): #成员方法(成员函数)
print("Hello!")
def PrintName(self):
print("姓名:",self.name,'年龄:',self.age)
def PrintNum(self):
print('num:',Person.num)
P1 = Person("Andy",22)
P2 = Person("Lily",23)
P1.PrintNum()
print(P1.name) #对象访问实例变量name
P1.PrintName()
P2.PrintNum()
print(P2.name)
P2.PrintName()
Person.num = 2 #修改类属性
print('num:',Person.num) #类访问类变量num
对象名._类名+私有成员
私有属性是为了数据封装和保密而设的属性,一般只能在类的成员方法(类的内部)中使用访问,不推荐从外部直接访问类的私有成员。
class Car:
price = 100000 #定义类属性
def __init__(self,c,w): #构造方法
self.color = c #定义公有属性color
self.__weight = w #定义私有属性__weight
car1 = Car('Red',10.5)
print(car1.color)
print(car1._Car__weight)
print(car1.__weight)
#AttributeError: 'Car' object has no attribute '__weight'
self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
self代表类的实例,而非类,类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
#%%方法
class Fruit:
price = 0 #类变量
def __init__(self): #构造方法
self.__color = 'Red' #定义和设置私有属性color
self.__city = 'Gansu'
def __outputColor(self): #定义私有方法
print(self.__color) #访问私有属性color
def __outputCity(self):
print(self.__city)
def output(self): #定义公有方法output()
self.__outputColor() #调用私有方法
self.__outputCity()
@ staticmethod
def getPrice(): #定义静态方法getPrice()
return Fruit.price
@ staticmethod
def setPrice(p):
Fruit.price = p
子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。
格式:
class 派生类名(基类名):
派生成员
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
class 派生类名(模块名.基类名):
方法重写必须出现在继承中,指在派生类继承了基类的方法之后,如果基类方法的功能不能满足需求,需要对基类中的某些方法进行修改。
Python继承中的特点:
例1:
class people:
name = '' #定义类变量
age = 0
__weight = 0 #定义私有属性,私有属性在类外部无法直接进行访问
def __init__(self,n,a,w): #定义构造方法
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#重写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"
%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
例2:
import types
class Person(object): #基类必须继承于object,否则在派生类中将无法使用super()函数
def __init__(self,name = '',age = 20,sex = 'man'):
self.setName(name)
self.setAge(age)
self.setSex(sex)
def setName(self,name):
if type(name)!=str:
print('姓名必须是字符串')
return
self.__name=name
def setAge(self,age):
if type(age)!=int:
print('年龄必须是数字')
return
self.__age = age
def setSex(self,sex):
if sex!='男'and sex!='女':
print('性别输入错误')
return
self.__sex=sex
def show(self):
print('姓名:',self.__name,'年龄:',self.__age,'性别:',self.__sex)
class Student(Person):
def __init__(self,name='',age=20,sex='man',schoolyear=2016):
super(Student,self).__init__(name,age,sex)
#Person.__init__(self,name,age,sex)
self.setSchoolyear(schoolyear)
def setSchoolyear(self,schoolyear):
self.__schoolyear = schoolyear
def show(self):
Person.show(self)
#super(Student,self).show()
print('入学年份:',self.__schoolyear)
zhangsan=Person('张三',19,'男')
zhangsan.show()
zhangsan.setAge(22)
zhangsan.show()
lisi=Student('李四',18,'男',2015)
lisi.show()
lisi.setAge(20)
lisi.show()
开闭原则,对扩展开放,对修改封闭
某个基类的继承类,其类型即属于这个派生类,又属于基类
四名牌手打牌,计算机随机将52张牌(不含大小王)发给4位牌手,并在屏幕上显示每位牌手的牌
class Card():
""" A playing card. """
RANKS = ["A", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "J", "Q", "K"] #牌面数字 1--13
SUITS = ["梅", "方", "红", "黑"] #梅为梅花,方为方钻,红为红心,黑为黑桃
def __init__(self, rank, suit, face_up = True):
self.rank = rank #指的是牌面数字 1--13
self.suit = suit #suit指的是花色
self.is_face_up = face_up #是否显示牌正面,True为正面,False为牌背面
def __str__(self): #print()
if self.is_face_up:
rep = self.suit + self.rank #+" "+ str(self.pic_order())
else:
rep = "XX"
return rep
def flip(self): #翻牌方法
self.is_face_up = not self.is_face_up
def pic_order(self): #牌的顺序号
if self.rank=="A":
FaceNum=1
elif self.rank=="J":
FaceNum=11
elif self.rank=="Q":
FaceNum=12
elif self.rank=="K":
FaceNum=13
else:
FaceNum=int(self.rank)
if self.suit=="梅":
Suit=1
elif self.suit=="方":
Suit=2
elif self.suit=="红":
Suit=3
else:
Suit=4
return (Suit - 1) * 13 + FaceNum
class Hand( ):
""" A hand of playing cards. """
def __init__(self):
self.cards = []
def __str__(self): #重写print()方法
if self.cards:
rep = ""
for card in self.cards:
rep += str(card) + "\t"
else:
rep = "无牌"
return rep
def clear(self):
self.cards = []
def add(self, card):
self.cards.append(card)
def give(self, card, other_hand):
self.cards.remove(card)
other_hand.add(card)
class Poke(Hand):
""" A deck of playing cards. """
def populate(self): #生成一副牌
for suit in Card.SUITS:
for rank in Card.RANKS:
self.add(Card(rank, suit))
def shuffle(self): #洗牌
import random
random.shuffle(self.cards) #打乱牌的顺序
def deal(self, hands, per_hand = 13): #发牌,发给玩家,每人默认13张牌
for rounds in range(per_hand):
for hand in hands:
top_card = self.cards[0]
self.cards.remove(top_card)
hand.add(top_card)
if __name__ == "__main__":
print("This is a module with classes for playing cards.")
#四个玩家
players = [Hand(),Hand(),Hand(),Hand()]
poke1 = Poke()
poke1.populate() #生成一副牌
poke1.shuffle() #洗牌
poke1.deal(players,13) #发给玩家每人13张牌
#显示4位牌手的牌
n=1
for hand in players:
print("牌手",n ,end=":")
print(hand)
n=n+1