1、对象 = 属性(静态的特征——>变量)+方法(动态动作——>函数)
2、类和对象的关系:类是抽象的,而对象是具体的。比如猫是一个类,而白猫就是一个对象。对象是类实例化的对象
3、默认类名以大写字母开头
4、函数和方法的区别在于,方法会默认有一个self
class Person :
name = '小朋友' #定义属性name,其中name的默认值为小朋友
def name(self):
print(self.name)
运行:
>>> a = Person()
>>> a.name()
小朋友
>>> b = Person #奇怪,为何这里Person没有括号,后面调用b.name()就提示错误?
>>> b.name()
TypeError: name() missing 1 required positional argument: 'self'
>>> c = Person() #而当Person后面带上括号之后,调用不带括号的c.name就无法显示具体内容?
>>> c.name
<bound method Person.name of <__main__.Person object at 0x000001C8A1DC3D48>>
>>>
答:首先你要明白类、类对象、 实例对象是三个不同的名词。
我们常说的类指的是类定义,由于"Python无处不对象”, 所以当类定义完之后,自然就是类对象。在这个时候,你可以对类的属性(变量)进行直接访问( MyClass.name )。
一个类可以实例化出无数的对象(实例对象) , Python 为了区分是哪个实例对象调用了方法,于是要求方法必须绑定(通过self参数)才能调用。而未实例化的类对象直接调用方法,因为缺少self参数,所以就会报错。
练习,定义一个矩形的类,并且有长宽的属性,和面积的方法
class Rectangle() :
def setRect(self,long,width):
self.long = long
self.width = width
print('矩形的长为%s宽为%s' % (self.long,self.width))
def getArea(self):
self = self.long*self.width
print(self)
运行:
>>> a = Rectangle()
>>> a.setRect(3,1)
矩形的长为3宽为1
>>> a.getArea()
3
>>> a.setRect(9,5)
矩形的长为9宽为5
>>> a.getArea()
45
另一法:
class Rectangle() :
long = 5 #确定属性,并且带默认值
width = 4
def setRect(self):
print('请输入长和宽')
self.long = float(input('长为:')) #input默认输入的为字符串,如果不进行转化的话在getArea史就会出现错误
self.width = float(input('宽为:'))
def getRect(self):
print('矩形的长为%s宽为%s' % (self.long,self.width))
def getArea(self):
return self.long*self.width
>>> a = Rectangle()
>>> a.getRect()
矩形的长为5宽为4
>>> a.setRect()
请输入长和宽
长为:9
宽为:6
>>> a.getArea()
54.0
>>>
一、面向对象的特征
- 封装,可以直接调用里面的函数,但是我们并不知道是怎么实现的
- 继承,子类共享父类数据和方法,拥有了他们的方法和属性
- 多态,不同对象对同一动作表现不一样(老虎‘跑’、乌龟‘爬’),调用同一个函数,但是显示不一样。
二、面向对象编程
1、self,不同调用传入self用以不同函数的识别,通俗来说就是不同房子(即实例)的门牌号
class Ball():
def setname(self,name):
self.name = name
def kick(self):
print('我是%s' % self.name)
运行:
>>> a = Ball()
>>> a.setname('足球')
>>> b = Ball()
>>> b.setname('篮球')
>>> a.kick() #调用同一个kick,但是里面的self不同,所以显示的球也就不同了
我是足球
>>> b.kick()
我是篮球
>>>
2、魔法方法,自动调用
__init__(self) #注意前后都是两根下划线。不然会报错。同时它只返回None,不会返回其它任何值,否则会报错。
__init__()
方法,在创建一个对象时默认被调用,不需要手动调用
__init__(self)
中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)
中除了self作为第一个形参外还需要2个形 参,例如__init__(self,x,y)
__init__(self)
中的self参数,python解释器会自动把当前的对象引用传递进去
class Ball: #定义一个类
def __init__(self,name): #初始化对象
self.name = name
def kick(self): #方法
print('我是%s' % self.name)
>>> a = Ball('足球') #创建了一个对象
>>> a.kick()
我是足球
for example :计算票价的小程序
class Ticket():
def __init__(self,weekend= False,child =False): #利用魔法方法把初始情况设置为成人非周末的状态,将成人儿童周末与常日的情况同一起来转换成折扣形式可以将情况抽象出来而不是拘束于分情况讨论
self.exp = 100
if weekend:
self.inc = 1.2
else:
self.inc = 1
if child:
self.discount = 0.5
else:
self.discount = 1
def calcPrice(self,num):
return self.exp * self.inc * self.discount * num
>>> adult = Ticket() #在输入状态下区分成人与儿童
>>> child = Ticket(child = True)
>>> print("2成人加上1小孩的平日票价为:%.2f" % (adult.calcPrice(2) + child.calcPrice(1)))
2成人加上1小孩的平日票价为:250.00
3、公有和私有
python默认对象的属性和方法都是公有的,外部可以调用和访问
name mangling 名字改编,只需要在变量或函数名前加‘__’两个下划线,就变成私有的,外部无法调用,只能内部调用 ,也可以 “_类名__变量名”
这样调用p._Person.__name
三、继承
1、基本语法
class Mylist(list) #继承list的属性,括号里面是父类
class Parent:
def hello(self):
print('正在调用父类的方法')
class Child(Parent):
pass
运行:
>>> a = Parent()
>>> a.hello()
正在调用父类的方法
>>> b = Child()
>>> b.hello() #这里继承了父类的方法,可以调用hello()
正在调用父类的方法
练习:定义一个点的类,定义一个直线的类,通过调用getLen()来实现获取直线的长度。
import math
class Point():
def __init__(self,x=0,y=0):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
class Line(Point):
def __init__(self,p1,p2):
self.x = p1.getX() - p2.getX()
self.y = p1.getY() - p2.getY()
self.len = math.sqrt(self.x*self.x+self.y*self.y)
def getLen(self):
return self.len
运行:
>>> p1 = Point(1,3)
>>> p2 = Point(2,5)
>>> line = Line(p1,p2)
>>> line.getLen()
2.23606797749979
>>>
2、注意!子类同名的方法会自动覆盖父类
- 子类同名的方法自动覆盖父类的益处
在此基础,继承父类部分属性的情况下进行修改,对于编程来讲可以节省力气。如果不需要部分函数功能,可以直接在函数之下加上pass,那么便没有任何反应。
- 用到 两种方法
- 调用未绑定的父类的方法
- 使用super 函数
class Shark(Fish):
def __init__(self):
Fish.__init__(self) #防止初始化覆盖,这里直接调用父类里面的初始化
self.hungry = True
class Shark(Fish):
def __init__(self):
super().__init__() #直接接上需要的父类的方法,不用给定任何父类的名字
self.hungry = True
3、多重继承,尽量少用——>钻石继承的陷阱
class C(Base1,Base2,Base3)