python学习笔记之--面向对象技术
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
方法:类中定义的函数。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
类:①属性(类变量和实例变量)
②方法(实例方法、类方法和静态方法)
类的定义
使用class语句来创建一个新类,class之后为类的名称,类名后有一括号,括号中为基类(可以有多个基类)然后以冒号结尾
类比说明:
生产杯子,杯子的模具(类),可以设定不同的参数来生产杯子。
设定好不同的参数(通过构造函数传参)
生产出具体的杯子(实例化)
#用class关键字来定义一个类 class Person: """文档字符串""" def __init__(self,name,age): if isinstance(age,int) and age >0: self.age = age else: self.age = 0 self.name = name def set_age(self,age): if isinstance(age,int) and age >0: self.age = age def get_age(self): return self.age p1=Person("wulaoshi",18) p2=Person("lilaoshi",28)
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
各种名词的实例示意
class Person: count = 0 #类变量 nation = "中国" def __init__(self,name,gender): #构造函数:只在实例化的时候才会调用 self.name = name #实例变量 self.gender = gender Person.count +=1 def get_name(self): #实例方法,必须要实例化 return self.name #类方法 @classmethod def get_instance_count(cls): return Person.count @classmethod def create_a_instance(cls): return Person("张","女") @staticmethod #静态方法 def get_nation(): return Person.nation wulaoshi = Person("吴老师","Male") #实例化:类名+(参数) lilaoshi = Person("李老师","Female")
实例化
class P: pass p=P() #这就是一个简单的实例化
class Person: def __init__(self,name): self.name = name p=Person("老王") #需要传参 print(p.name)
类变量
class Person: x=0 #类变量 def __init__(self,name): self.name = name Person.x+=1 #类名.类变量 来访问类 def get_name(self): print(self.name) p1=Person("wulaoshi") p2=Person("laoli") p3=Person("laoli") print(Person.x) print(p1.x) print(p2.x)
运行结果:
E:\>py -3 a.py
3
3
3
实例变量
通俗来讲,在类里定义的前面加self.xxxx的变量就是实例变量。
思考:类变量和实例变量的区别?
答:类变量定义在类里的函数体之外,只有一份全局生效;实例变量只在方法体内部生效,在同一个类里面可以夸方法访问,可以有0个、1个或多个。
class Person: def __init__(self,name,gender,age): self.name = name #实例变量 self.gender = gender #实例变量 age = age #局部变量 def get_name(self): #实例方法,必须要实例化 return self.name def get_age(self): return self.age xiaoli = Person("小李","Male",18) print(xiaoli.get_name()) #用实例对象来调用实例方法 print(Person("小李","Male",18).get_nam()) #用实例来调用实例方法 print(xiaoli.get_age()) #局部变量不能夸方法访问
E:\>py -3 a.py
小李
小李
Traceback (most recent call last):
File “a.py”, line 20, in <module>
print(xiaoli.get_age())
File “a.py”, line 13, in get_age
return self.age
AttributeError: \’Person\’ object has no attribute \’age\’
构造函数
__inint__是python的内置方法,该方法在类实例化时会自动调用
class Person: def __init__(self,name): #构造方法,用来初始化的,也可以不传参数 self.name = name p = Person("xz") #类的实例化操作会自动调用 __init__() 方法 print(p.name)
E:\>py -3 a.py
xz
self的含义
self代表类的实例,而非类。
self传递的是某个实例的地址。实例地址里面的所有变量都可以在方法中进行使用。
class P: def __init__(self,value): self.value = value def get(self): #实例方法 return "***:"+str(self.value) def set(self,value): #实例方法 if isinstance(value,(int,float)): self.value = value return None p1 =P(1) p2 =P(2) p3 =P(3) \'\'\' 内存中的位置:A P:类变量 类定义的方法 内存中的位置:b p1的实例:self.value=1 内存中的位置:c p2的实例:self.value=2 内存中的位置:d p3的实例:self.value=3 \'\'\' #调用过程解析: \'\'\' p1.get()--->会把内存位置b发送给类定义的方法P.get self:是一个方法的参数,指向内存位置b。 get方法会从内存b的位置找到,value值,然后执行方法中的代码。 \'\'\'
总结:
私有变量
什么情况需要使用私有变量?
下面来看一个场景示例:
class Person: def __init__(self,name,age): if isinstance(age,int) and age >0: self.age = age else: self.age = 0 self.name = name def set_age(self,age): if isinstance(age,int) and age >0: self.age = age def get_age(self): return self.age p1=Person("wulaoshi",18) p2=Person("lilaoshi",28) p1.age=-1 #虽然制定了一些规则(方法)来保证数据的安全性,但是如果绕过方法直接给变量赋一个值,还是可以把它改成不合法的数据;这个时候就需要用私有变量来限制外部对变量的操作 print(p1.age)
class Person: def __init__(self,name,age): if isinstance(age,int) and age >0: self.__age = age else: self.__age = 0 self.name = name #为什么要写一下self.name=name,self.name叫实例变量,name叫局部变量,如果不写self.name=name在类的其他方法里就不能在使用name这个变量 def set_age(self,age): if isinstance(age,int) and age >0: self.__age = age def get_age(self): return self.__age p1=Person("wulaoshi",18) p2=Person("lilaoshi",28) #print(p1.__age) #这里如果外部访问私有变量会报错:AttributeError: \'Person\' object has no attribute \'__age\' p1.__age=100 #这里被认知直接给__age赋值,不是方法里实例变量的值 print(p1.__age) #打印100 print(p1.get_age()) #打印18
方法
操作属性的动作叫方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
➢普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
➢类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
➢静态方法:由类调用;无默认参数
#encoding=utf-8 class Foo: def __init__(self, name): self.name = name #实例方法 def ord_func(self): """ 定义普通方法,至少有一个self参数 """ # print self.name print (\'普通方法\') #类方法 @classmethod def class_func(cls): """ 定义类方法,至少有一个cls参数 """ print (\'类方法\')
#静态方法 @staticmethod def static_func(): """ 定义静态方法 ,无默认参数""" print (\'静态方法\') f=Foo("吴老师")
#调用实例方法 f.ord_func()
#调用类方法 Foo.class_func() f.class_func()
#调用静态方法 Foo.static_func() f.static_func()
私有方法
类中方法名前面有两个下划线,表示是Python中的私有方法,不能在类外部调用(如__setId()),在类内部调用语法: self.__private_methods。
#coding=utf-8 class Person(object): id = 12 #类静态成员在这儿定义,注意缩进 def __init__(self,name): self.name = name self.__inName = \'ads\' def __setId(self,id): #隐藏方法 Person.id = id * 2 def getId(self): self.__setId(18) #类内部调用隐藏方法 return Person.id p = Person("prel") print (p.getId()) print ("类外部调用私有方法") print (p.__setId(10))
使用函数添加、删除、修改、访问类属性
可以使用以下函数来操作对象的属性:
1、getattr(obj, name[, default]) : 访问对象的属性,如果存在返回对象属性的值,否则抛出AttributeError异常。
2、hasattr(obj,name) : 检查是否存在某个属性,存在返回True,否则返回False。
3、setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性,该函数无返回值。若存在则更新这个值
4、delattr(obj, name) : 删除属性,如果属性不存在则抛出AttributeError异常,该函数也无返回值。
class Person: count =0 #类变量 def __init__(self,name): #构造方法 self.name =name Person.count+=1 def get_name(self): return self.name print(getattr(p,"name")) print(p.name) print(getattr(p,"name","name not exist!")) setattr(p,"name","李老师") print(getattr(p,"name")) print(hasattr(p,"name1")) print(delattr(p,"name"))