一、前言:我为什么要用类?
上栗子:大鱼吃小鱼游戏
这个游戏里有不同的鱼,要想用代码构建每一条鱼似乎很费劲;假设我们先制作一条鱼
import random as r
class Fish():
def __init__(self,name): #实例化时传入要制作的鱼的名字
self.name = name
self.x = r.randint(0,10)
self.y = r.randint(0,10)
def makeName(self):
print("我的名字是:%s" %(self.name))
def makeColour(self):
print("我的颜色是红色")
def makeMouth(self):
print("小嘴")
def makeTail(self):
print("小尾巴")
def makeEye(self):
print("圆眼睛")
def move(self):
self.x -= 1
print("我的位置是:",self.x,self.y)
我们以同样的方法不停造鱼…这时雪花般的代码出现了…
细细观察,游戏中除了鱼的大小、颜色外其他都一致,也许它们都出自一条鱼,即继承了第一条鱼(父级)的所有属性与方法,当然,它们也可以选择性不继承父级方法里的颜色与大小,自己在创建一个颜色(方法)从而在共性中有所差异。
import random as r
class Fish(): #父级
def __init__(self,name): #实例化时传入要制作的鱼的名字
self.name = name
self.x = r.randint(0,10)
self.y = r.randint(0,10)
def makeName(self):
print("我的名字是:%s" %(self.name))
def makeColour(self):
print("我的颜色是红色")
def makeMouth(self):
print("小嘴")
def makeTail(self):
print("小尾巴")
def makeEye(self):
print("圆眼睛")
def makeAll(self):
self.makeName()
self.makeColour()
self.makeMouth()
self.makeTail()
self.makeEye()
self.x -= 1
print("我的位置是:",self.x,self.y)def move(self):
class Goldfish(Fish): #括号里写Fish,意思为前者继承后者所有特性
def makeColour(self):
print("我的颜色是金色")
class Carp(Fish):
pass
class Salmon(Fish):
pass
class Shark(Fish):
## def __init__(self): #子类重写了父类的方法就会覆盖掉父类方法,意味着我们要把这个方法制作细节改成我们想要的
## super().__init__() #自动找出父类方法
## self.hungry = True 若不重写父类方法,(父类的方法还在子类中隐性存在)
def eat(self):
self.hungry = True
if self.hungry:
print("我要吃了你")
self.hungry = False
else:
print("吃不下了")
#最后我们用以下代码造鱼。
fish = Fish("smallfish") #实例化对象
goldfish = Goldfish("Goldfish") #实例化对象
fish.makeAll() #完善对象
Goldfish.makeAll() #完善对象
二、类与对象:
1、二者关系、上面的例子中可知:class Fish(): #父级 这个Fish() 就是个抽象的鱼的类,但我们无法得知其具体实物;我们可以给class Fish()传入实例化对象
fish = Fish("smallfish")
即:类是对客观世界中事物得抽象,而对象是类实例化后的实体
2、类的定义:
(1)python使用class关键字定义一个类,类名的首字母一般要大写:
例如:
class Student: #定义了一个Student类
(2)类的主体由一系列的属性和方法组成
例如:
class Student: #定义一个类
def __init__(self): #**类的构造函数**,用于**初始化类的内部状态,为类的属性设置默认值**
self.name=name #定义name属性
self.color=color #定义color属性
def grow(self): #定义一个函数,为类的函数,称为方法;它至少有一个参数self
print(‘Student grow’)
附:__init__方法的第一参数永远是self,表示创建的类实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器会自己把实例变量传进去。
如果不提供__init__方法,python将会给出一个默认的__init__方法
另外,这里self就是指类本身,self.name就是Student类的属性变量,是Student类所有。而name是外部传来的参数,不是Student类所自带的。故,self.name = name的意思就是把外部传来的参数name的值赋值给Student类自己的属性变量self.name
3、类的属性
(1) python的属性分为实例属性和静态属性,实例属性是以self为前缀的属性,如果构造函数中定义的属性没有使用self作为前缀声明,则该变量只是普通的局部变量,类中其它方法定义的变量也只是局部变量,而非类的实例属性。
例如:
import random as r
class Fish:
def __init__(self):
self.x = r.randint(0,10) #全局变量,实例属性
self.y = r.randint(0,10)
def move(self):
self.x -= 1
print("我的位置是:",self.x,self.y)`
#局部变量,静态属性(报错)
import random as r
class Fish:
def __init__(self):
x = r.randint(0,10)
y = r.randint(0,10)
def move(self):
x -= 1
print("我的位置是:",x,y)
也就说定义类,必须加self
(2)类的属性:一般分为公有属性和私有属性,默认情况下所有得属性都是公有的,如果属性的名字以两个下划线开始,就表示为私有属性,没有下划线开始的表示公有属性。
##公有与私有 定义私有变量只需要在变量名或函数前加上“__”
class Person:
name = "小鸡"
p = Person()
print(p.name)
class Person:
__name = "小鸡"
p = Person()
print(p.__name)
class Person:
__name = "小鸡"
def getName(self):
return self.__name
p = Person()
print(p.getName())
"""注意:python的类和对象都可以访问类属性;
类的外部不能直接访问私有属性(属性名以两个下划线开始),否则出现undefined。"""