python基础-面向对象(类)
类
- 类的定义
>>> class P:
... pass
...
>>> P
<class __main__.P at 0x0000000001F4B828>
类对象:只有具备自己的一些属性+操作这些属性的方法就可以成为对象,因为类也是对象
类是模板
类对象的使用:
#coding=utf-8
#类变量声明:变量名 =xxx (全局变量)
#类变量调用:类名.变量名
#实例变量赋值:self.变量名 = xxx
#调用实例变量:self.变量名
#class TOY: #经典类
class TOY(object): #新式类
TOY_NUMBER =0 #类变量
def __init__(self,length,width,height,colour): #构造函数
self.length = length #实例变量
self.width = width #实例变量
self.height = height #实例变量
self.colour =colour #实例变量
TOY.TOY_NUMBER +=1 #操作类变量
def get_size(self): #实例方法定义必须有self
#self表示未来调用此方法的具体实例
return self.length,self.width,self.height
def get_colour(self):#实例方法
return self.colour
print TOY.TOY_NUMBER
duck = TOY(1,1,1,"yellow") #实例化是生成实例的过程
duck.voice = "gaga"
print duck.voice
print duck
print duck.get_size()
print duck.get_colour()
print duck.height #调用类的实例变量
print TOY.TOY_NUMBER
dog = TOY(10,10,10,"white")
print TOY.TOY_NUMBER
- 类的实例化(从模板生成一个东西的过程就是实例化)
>>> x
<__main__.P instance at 0x0000000002795F08>
实例化对象:实例化后的结果就是实例化对象
实例是利用模板造出来的东西
实例是实例化之后的结果。实例化是一个过程。
练习:
- 创建类
#coding=utf-8
class Employee(object):
#所有员工基类
empCount = 0
def __init__(self, name, salary) :
#类的构造函数
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self) :
#类方法
print "total employee ",Employee.empCount
def displayEmployee(self) :
print "name :",self.name , ", salary :", self.salary
def f(self):
self.displayEmployee()
e=Employee("wulaoshi","10k")
e.f()
类变量要用类名.变量名调用;实际变量要用实例变量名.变量名调用
实例变量也可以调用类变量,实例变量名.类变量名 此时会生成实例变量,不会影响类变量,只是两个变量重名。
实例:成员变量(我要操作的数据)+方法(我怎么操作这组数据)
实例:成员变量(类属性:类变量和实例变量)+方法(1 实例方法 2 静态方法 类方法)
4、类方法、实例方法、和静态方法
#encoding=utf-8
class Person:
count=0
def get_name(self):
#实例方法
self.f=1
Person.count=10
return "gloryroad!"
@classmethod #类方法
def get_sex(cls,sex):
#self.f=1 # 类方法和静态方法都不能使用实例化变量
Person.count=20 #类方法、静态方法、实例方法都可以调用类变量
return sex
@staticmethod #静态方法
def get_height(height):
#self.f=1
Person.count=30
return height
print Person.get_sex("male") #类方法和静态方法不需要实例化就能直接调用;也可以实例化之后用实例化变量去调用
print Person.get_height(180)
p=Person()
print p.get_name()
小练习:
写一个类,有3种类方法
实例方法
类方法
静态方法
用类调用,一种是用实例调用,分别调用一下
#coding=utf-8
class BIRD:
"""gloryroad bird!"""
REVOKE_COUNT =0
sex = "male"
def __init__(self,name):
self.name
=name +" in the sanya"
def get_name(self):
BIRD.REVOKE_COUNT +=1
print "REVOKE_COUNT:",BIRD.REVOKE_COUNT
return self.name
@classmethod
def set_sex(cls,sex):
print cls.__module__
BIRD.sex = sex
return BIRD.sex
@staticmethod
def set_voice(voice):
BIRD.voice =voice
#print self.name
return BIRD.voice
b=BIRD("seagull2")
print b.get_name()
print BIRD.set_sex("f")
print b.set_sex("m")
print BIRD.set_voice("a.......")
print b.set_voice("a.......")
#函数里面的传入参数:局部变量
#带有类名调用的变量:类变量
#带有self的变量:实例变量
#方法里面的局部变量:既没有类名,也没有self,在方法里声明和使用
#方法执行完毕,则局部变量被释放掉,且无法使用。
#类方法:可以被实例和类分别调用,可以使用类变量,不可以使用实例变量
# 类方法可以仅使用类名做调用,即不需要生成实例,所以不能使用
# 实例变量
#实例方法:可以使用实例变量,可以使用类变量。
#静态方法:不支持实例变量,理由同类方法,不使用附加的self,cls参数
#可以支持类和实例分别调用
- 调用
调用被封装的内容时,有两种情况:
➢通过对象直接调用
➢通过 self 间接调用
实例化变量 增、删、改
#coding=utf-8
class BIRD:
def __init__(self,name):
print "name1"
b=BIRD("seagull")
b.age =1
print b.age
del b.age
print b.age
类变量增、删、改
#coding=utf-8
class BIRD:
def __init__(self,name):
print "name1"
b=BIRD("seagull")
BIRD.age = 11
print BIRD.age
BIRD.age = 12
print BIRD.age
del BIRD.age
print BIRD.age
实例是可以调用类变量的,因此当类变量名和实例变量名同名时,删除了实例变量,再去调用时会自动去找到类变量,因此下面的例子没有报错
#enconding = utf-8
class BIRD:
def __init__(self,name):
print "name1"
b=BIRD("s1")
b.age = 111
print b.age
BIRD.age = 11
print BIRD.age
del b.age
print b.age
#enconding = utf-8
class BIRD:
def __init__(self,name):
print "name1"
b=BIRD("s1")
b.age = 111
print b.age
BIRD.age = 11
print BIRD.age
del b.age
print b.age
del b.age
print b.age
但是二次删除就找不到类变量了,就会报错了
- 经典类的属性
#encoding=utf-8
class Foo:
def func(self):
print "func!"
# 定义属性
@property
def prop(self):
# log.info (“gloryroad”)
return "gloryroad"
# ############### 调用 ###############
foo_obj = Foo()
foo_obj.func()
print foo_obj.prop #调用属性
方法:foo_obj.func()
属性:foo_obj.prop
@property装饰器就是负责把一个方法变成属性调用的
- 新式类的属性
#encoding=utf-8
class Goods(object):
@property
def price(self):
print '@property'
@price.setter
def price(self, value):
print '@price.setter'
@price.deleter
def price(self):
print '@price.deleter'
# ############### 调用
obj = Goods()
obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123 # 自动执行 @price.setter修饰的 price 方法,并将 123 赋值给方法的参数
del obj.price # # 自动执行 @price.deleter修饰的 price 方法
小练习:自行修改setter,控制值在100到1000直接才能修改,否则不能修改
#encoding=utf-8
class Goods(object):
@property
def price(self):
print '@property'
@price.setter
def price(self, value):
if not isinstance(value,int):
raise ValueError('price must be an integer!')
if value<100 or value>1000:
raise ValueError('price must between 100~1000!')
self._price = value
@price.deleter
def price(self):
print '@price.deleter'
# ############### 调用
obj = Goods()
obj.price
obj.price = 120
print obj._price
del obj.price
老师的方法:
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
@property
def price(self):
print '@property'
return self.value
@price.setter
def price(self, value):
print '@price.setter'
if value >=100 and value <=1000:
self.value = value
@price.deleter
def price(self):
print '@price.deleter'
del self.value
# ############### 调用
obj = Goods(100)
print obj.price
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并
print obj.price
del obj.price # 自动执行 @price.deleter 修饰的 price 方法
#print obj.price
注意:只适用于新式类
新式类中的属性有三种访问方式,并分别对应了三个被@property、 @方法名.setter、 @方法名.deleter修饰的方法
- 使用函数添加、删除、修改、访问类属性
getattr(obj, name[, default]) : 访问对象的属性,如果存在返回对象属性的值,
否则抛出AttributeError异常
(1)访问的属性不存在,且无默认返回值
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
print getattr(obj,"value1")
(2)访问的属性不存在,默认返回值为“000000”
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
print getattr(obj,"value1","000000")
(3)访问的属性存在
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
print getattr(obj,"value")
hasattr(obj,name) : 检查是否存在某个属性,存在返回True,否则返回False
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
print hasattr(obj,"value")
print hasattr(obj,"value1")
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性,该函数无返回值。若存在则更新这个值
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
setattr(obj,"value",1111)
print obj.value
setattr(obj,"value1",2222)
print obj.value1
delattr(obj, name) : 删除属性,如果属性不存在则抛出AttributeError异常,该函数也无返回值。
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
setattr(obj,"value",1111)
print obj.value
setattr(obj,"value1",2222)
print obj.value1
delattr(obj,"value1")
delattr(obj,"value2")
小练习:判断是否存在,如果存在就删除并提示删除成功
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
setattr(obj,"value",1111)
print obj.value
setattr(obj,"value1",2222)
print obj.value1
if hasattr(obj,"value1"):
delattr(obj,"value1")
print "del success"
- Python内置类属性
Python有如下内置的类属性:
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串,也就是类的帮助信息。
__name__: 类名
__module__: 类定义所在的模块(类的全名是’ __main__.className’ ,如果类位于一个导入模块mymod中,那么className.__module__ 等于mymod)
__bases__ : 类的所有父类(包含了所有父类组成的元组)
#encoding=utf-8
class Goods(object):
def __init__(self,value):
self.value = value
obj = Goods(100)
print Goods.__dict__
print"--"*50
print Goods.__doc__
print"--"*50
print Goods.__name__
print"--"*50
print Goods.__module__
print"--"*50
print Goods.__bases__
常量举例:
#coding=utf-8
class _const:
class ConstError(TypeError):pass
def __setattr__(self, name, value):
if self.__dict__.has_key(name):
raise self.ConstError, "Can't rebind const (%s)" %name
self.__dict__[name]=value
import sys
print __name__
sys.modules[__name__] = _const()
小练习:导入了其他的木块,想确定使用的某个类在哪个包里面,可以用__module__获取
a.py:
#encoding=utf-8
class Goods(object):
"""good class """
def __init__(self,value):
self.value = value
self.name
= "name"
def get_name(self):
return "goods name"
# ############### 调用
obj = Goods(100)
#print Goods.__module__
b.py
#coding=utf-8
import b
print b.Goods.__module__
- 类变量
修改类变量:
#encoding=utf-8
class Goods(object):
"""good class """
num = 100
def __init__(self,value):
self.value = value
self.name = "name"
@staticmethod
def set_num():
Goods.num =1
# ############### 调用
obj = Goods(100)
obj.set_num()
print obj.num
- 小结几种方法的区别
类方法可以被类对象或实例调用,实例方法只能被实例调用,它只属于类的单个实例拥有,静态方法两者都能调用,它在类和实例间共享。 Python实现了一定的灵活性使得类方法和静态方法,都能够被实例和类二者调用。
所以三者主要区别在于参数传递上的区别,实例方法隐含传的参数是类实例self,而类方法隐含传递的参数是类本身cls,而静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
- Python类中隐藏数据
__init 两个__ 下划线的是私有方法
私有方法在类的内部可以随意调用,外部不能随便调用
#encoding=utf-8
class Goods(object):
"""good class """
num = 100
def __init__(self,value):
self.value = value
self.name= "name"
def __func(self): #私有方法
print "private method"
def get_name(self):
self.__func()
# ############### 调用
obj = Goods(100)
obj.get_name() #通过get_name间接调用私有方法self.__func()
练习:自己写一个私有方法并调用
#encoding=utf-8
class Goods(object):
"""good class """
num = 100
def __init__(self,value):
self.value = value
self.name= "name"
def __test(self):
print "private method"
def get_name(self):
self.__test()
# ############### 调用
obj = Goods(100)
#obj.test() #在类外部直接调用私有方法是不可以的
obj.get_name()
- 类的私有属性
#encoding=utf-8
class Goods(object):
"""good class """
__num = 100
def __init__(self,value):
self.value = value
self.__name = "name"
def get_name(self):
print Goods.__num
print self.__name
# ############### 调用
obj = Goods(100)
print obj.get_name()
练习:自己定义类的私有属性,并在类外部调用
#encoding=utf-8
class Goods(object):
"""good class """
__num = 100
def __init__(self,value):
self.value = value
self.__name= "name" #这里得用self调用,直接用Goods不行
def test(self):
print Goods.__num
print self.__name
# ############### 调用
obj = Goods(100)
#print Goods.__num
#print Goods.__name
print obj.test()
- 但是私有也可以通过特殊方法进行修改
#encoding=utf-8
class Goods(object):
"""good class """
__num = 100
def __init__(self,value):
self.value = value
self.__name = "name"
def get_name(self):
print Goods.__num
print self.__name
# ############### 调用
obj = Goods(100)
obj._Goods__name = "gloryroad!"
print obj._Goods__name
- 单继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。即一个派生类(derived class)继承基类(bass class)字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
#encoding=utf-8
class BIRD(object):
def __init__(self,category):
self.category = category
def get_name(self):
return "BIRD"
@classmethod
def get_age(cls):
return 20
@staticmethod
def get_sex():
return "Male"
class CHINA_BIRD(BIRD):
def get_voice(self):
return "jiujiu!"
class US_BIRD(BIRD):
def get_voice(self):
return "gaga!"
cb = CHINA_BIRD("Fly")
ub = US_BIRD("Fly")
print cb.category
print CHINA_BIRD.get_age()
print cb.get_age()
print CHINA_BIRD.get_sex()
print cb.get_sex()
print cb.get_voice()
print ub.get_voice()
练习:写一个人的类,实现继承,并通过子类实例化后调用父类方法
#encoding=utf-8
class Person(object):
def __init__(self,name):
self.name = name
def get_sex(self):
return "male"
@classmethod
def get_age(cls):
return 25
@staticmethod
def get_height():
return 175
class China_person(Person):
def get_haircolour(self):
return "black"
class English_person(Person):
def get_haircolour(self):
return "yellow"
person1 = China_person("qwq")
print person1.get_sex()
print person1.get_age()
print person1.get_haircolour()
person2 = English_person("Amilly")
print person2.get_age()
print person2.get_height()
print person2.get_haircolour()
继承举例:
#encoding=utf-8
class Animal:
def eat(self):
print u"%s 吃 " %self.name
def drink(self):
print u"%s 喝 " %self.name
def shit(self):
print u"%s 拉 " %self.name
def pee(self):
print u"%s 撒 " %self.name
class Cat(Animal):
def __init__(self, name):
self.name = name
self.breed = u'猫'
def cry(self):
print u'喵喵叫'
class Dog(Animal):
def __init__(self, name):
self.name = name
self.breed = u'狗'
def cry(self):
print u'汪汪叫'
# ######### 执行 #########
c1 = Cat(u'小白家的小黑猫')
c1.eat()
c2 = Cat(u'小黑的小白猫')
c2.drink()
d1 = Dog(u'胖子家的小瘦狗')
d1.eat()
- 子类调用积累方法
#coding=utf-8
class Parent(object): # define parent class
parentAttr = 100
def __init__(self):
"父类构造方法,用于初始化工作"
print "Calling parent constructor"
def parentMethod(self):
print 'Calling parent method'
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print "Parent attribute :", Parent.parentAttr
class Child1(Parent): # define child1 class
def __init__(self):
"子类构造方法,用于初始化子类本身数据的工作"
print "Calling child1 constructor"
def childMethod(self):
print 'Calling child1 method'
Parent.parentMethod(self) #调用基类的方法,所以要加上参数self
class Child2(Parent): # define child2 class
#没有实现__init__方法,则会调用基类的__init__方法
def childMethod(self):
print 'Calling child2 method'
self.parentMethod() #子类调用自己从父类那继承过来的父类的方法
c1 = Child1() # 实例化子类 1
c2 = Child2() # 实例化子类 2
c1.childMethod() # 调用子类1的方法
c2.childMethod() # 调用子类2的方法
c1.parentMethod() # 子类实例对象调用父类方法
c1.setAttr(200) # 再次调用父类的方法
c1.getAttr() # 再次调用父类的方法
- 方法重写
#coding=utf-8
class P:
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
P.__init__(self,x)
def get_name(self):
print "S1"
s = S1("gloryroad")
#子类会自动调用基类的构造函数,参数会自动传到基类
s.get_name()
- 子类调用父类的方法
调用父类的方法1:
#coding=utf-8
class P:
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
P.__init__(self,x)
def get_name(self):
P.get_name(self)
s = S1("gloryroad")
s.get_name()
调用父类的方法2:
#coding=utf-8
class P:
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
P.__init__(self,x)
s = S1("gloryroad")
s.get_name()
调用父类的方法3:
#coding=utf-8
class P:
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
P.__init__(self,x)
def func(self):
self.get_name()
s = S1("gloryroad")
s.func()
- 调用父类的__init__方法
子类调用基类的构造函数有两种方法,基本语法如下:
1、 super(subclassName, self).__init__( [parameter1[,parameter2....]])
2、 superclassName.__init__(self, [parameter1[,parameter2....]])
注意:
两次参数列表中的self参数都是必不可少的,如果基类的构造方法中有除了self参数外别的参数,调用时,也必须传入同等数量、同等类型的参数。
当子类不定义自己的构造方法时,默认会自动调用父类的构造方法。Python中super函数只能在构造方法中使用。
方法一:
#encoding=utf-8
class A(object):
name=''
def __init__(self,x):
self.name
='fosterwu'
def getName(self):
return 'A ' + self.name
class C(A):
def __init__(self,x):
super(C, self).__init__(x) #调用基类构造方法
if __name__=='__main__':
c = C("g")
print c.getName()
方法二:
#coding=utf-8
class P(object):
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
super(S1,self).__init__(x)
def func(self):
self.get_name()
s = S1("gloryroad")
#子类会自动调用基类的构造函数,参数会自动传到基类
s.func()
- 类间的关系判断
#coding=utf-8
class P(object):
def __init__(self,name):
print u"父类被初始化"
print name
def get_name(self):
print "P"
class S1(P):
def __init__(self,x):
print u"子类被初始化"
super(S1,self).__init__(x)
def func(self):
self.get_name()
s = S1("gloryroad")
print issubclass(S1,P)
print isinstance(s,P)
print isinstance(s,S1)
- 多重继承
多重继承中,子类在没有定义自己的构造方法时,以第一个父类为中心。
如果子类重新定义了自己的构造方法,就不会调用父类的构造方法。但如果仍想调用父类的构造方法,这个时候调用哪个父类的构造方法,由你自己确定,并且多重继承时,调用具体哪个父类的构造方法时只能使用如下方法:
superclassName.__init__(self, [parameter1[,parameter2....]] )
如果父类中有同名的方法时,通过子类的实例对象去调用的该方法也是第一个父类中的方法。同样你可以用我们上边说的“子类调用基类方法”中的的方法去调用具体哪个父类中的方法。 Parent.parentMethod(self)
代码示例:没有自己的构造函数时默认调用第一个继承类
#coding=utf-8
class P(object):
def __init__(self,name):
print "P constructor"
self.name =name
self.age =100
def fuc(self):
print "P:func"
def p_fuc(self):
print "P_func"
class S(object):
def __init__(self,x):
print "S constructor"
self.name =x
self.sex = "male"
def fuc(self):
print "s:func"
def s_fuc(self):
print "s_func"
class A(P,S):
pass
a =A("gloryroad")
示例二:子类有自己的构造函数会调用自己的
#coding=utf-8
class P(object):
def __init__(self,name):
print "P constructor"
self.name =name
self.age =100
def fuc(self):
print "P:func"
def p_fuc(self):
print "P_func"
class S(object):
def __init__(self,x):
print "S constructor"
self.name =x
self.sex = "male"
def fuc(self):
print "s:func"
def s_fuc(self):
print "s_func"
class A(P,S):
def __init__(self):
print "A constructor"
a =A()
示例三:集成的多个类中有重名的方法,调用时会默认用第一个
#coding=utf-8
class P(object):
def __init__(self,name):
print "P constructor"
self.name =name
self.age =100
def func(self):
print "P:func"
def p_func(self):
print "P_func"
class S(object):
def __init__(self,x):
print "S constructor"
self.name =x
self.sex = "male"
def func(self):
print "s:func"
def s_func(self):
print "s_func"
class A(P,S):
pass
a =A("gloryroad")
a.func()
a.p_func()
a.s_func()
示例四:在子类中把继承的父类都做初始化,这样都可以进行调用且不会出错。
#coding=utf-8
class P(object):
def __init__(self,name):
print "P constructor"
self.name =name
self.age =100
def func(self):
print "P:func"
def p_func(self):
print "P_func"
class S(object):
def __init__(self,x):
print "S constructor"
self.name =x
self.sex = "male"
def func(self):
print "s:func"
def s_func(self):
print "s_func"
class A(P,S):
def __init__(self,name):
P.__init__(self,"gloryroad") #把继承的父类都做初始化,后面想调用哪个都可以,而且不会出错
S.__init__(self,"gr")
def func(self):
S.func(self)
a =A("gloryroad")
a.func()
总结:
#coding=utf-8
经典类、新式类(object)
类变量、实例变量、局部变量、属性@property :增删改查
实例方法、类方法、静态方法
私有变量、私有方法分别前面加“__“,只能在类内部可以调用
构造函数:实例化对象的时候,自动调用,可以有参数也可以没有
如果一个类没有构造函数,系统自动给你加一个。
继承:
单继承:一个基类
没有构造函数,自动调用基类的构造函数
有构造函数,则不会自动调用基类的构造函数
建议:子类定义构造函数,且显示调用基类的构造函数
显示调用基类的构造函数的2个方法:
推荐使用的(多重继承可以使用):superclassname.__init__(self,param1,param2....)
不推荐使用:super(subclassname,self).__init__(param1,param2....)
子类可以获取所有父类的全部方法、类变量和实例变量
如果子类中有同名的变量和方法,则会覆盖(隐藏)父类的内容
多继承:多个基类
如果没有实现子类的构造函数,会以第一个基类为中心,进行初始化
如果子类调用基类的方法,且多个基类有同名方法,则会以第一个基类为中心
如果不想调用第一个,superclassname.methodname(self)
建议:所有的子类都有构造函数,且同时初始化所有父类的构造函数
类的用途:
1 抽象共性,做继承
2 仅用于数据和方法的封装,方便调用
例如:excel类:
数据:某excel文件、sheet
操作的方法:
excel文件、sheet数据的增删改查