文章目录
面向对象的三大特性:继承、封装、多态。
1.创建类
所创建的类中,每一个方法的self参数是必需的(不一定要叫self,也可以是任何其他名字)。在调用方法时,这个参数的值不需要自己传递,系统会将方法所属的对象传入这个参数。而且在方法内部可以利用这个参数调用对象本身的资源(如属性、方法等)。
class Person: #创建一个Person类
def setname(self,name): #定义setname方法
self.name=name
def getname(self):
return self.name
def greet(self):
print("Hello,I'm {name}".format(name=self.name))
person1=Person() #创建person1对象
person2=Person() #创建person2对象
person1.setname("Bill gates") #调用person1对象的setname方法
person2.name="Bill clinton" #调用person2对象的name属性
print(person2.name) #Output:Bill clinton
#调用person1对象的greet方法的两种方式:
person1.greet() #Output:Hello,I'm Bill gates
Person.greet(person1) #Output:Hello,I'm Bill gates
2.方法和私有化
Python类默认情况下所有的方法都可以被外部访问。不过如Java、C#等语言都提供了private关键字将方法私有化(即只有类的内部方法才能访问私有化的方法)。但python并没有提供类似的关键字将方法私有化,所以我们只能迂回解决。
在Python类的方法名前面加双下划线(__)可以让该方法在外部不可访问。但并非绝对的不可访问,Python编译器并没有将其真正的私有化,而是把会将"__methodName"的方法名改成"_ClassName__methodName"的形式。
class Person:
def method1(self): #公共方法
print("method1")
def __method2(self): #私有方法
print("method2")
p=Person()
p.method1() #Output:method1
p.__method2() #抛出异常
p._Person__method2() #Output:method2
3.类代码块
class定义的类会立即执行代码块中可以立即执行的语句(如print函数)。
在创建MyClass类实例后,可以动态向MyClass对象添加新变量。
class MyClass:
print("MyClass") #class块中的语句会立刻执行
count=0
def counter(self):
self.count+=1
#Output:MyClass
m=MyClass()
m.counter()
print(m.count) #Output:1
m.counter()
print(m.count) #Output:2
m.count="abc" #将count变量改成字符串类型
print(m.count) #Output:abc
m.name="Mike" #向m对象动态添加name变量
print(m.name) #Output:Mike
4.类的继承
类的继承指一个类(子类)从另外一个类(父类)中获得了所有的成员。父类的成员可以在子类中使用,就像子类本身的成员一样。
①检测继承关系:issubclass函数
issubclass函数可以判断类与类之间的关系(该函数接收两个参数,第1个参数是子类,第2个参数是父类,是继承关系返回True,否则返回False)。
②显示已知类的父类:__bases __
②如果想要知道已知类的父类(们),可以直接使用"__ bases __ ",这是类的一个特殊属性。
③检测一个对象是否是某一个类的实例:isinstance函数
isinstance函数可以检测一个对象是否是某一个类的实例(该函数接收两参数,第1个参数是要检测的对象,第2个参数是一个类,如果第1个参数指定的对象是第2个参数指定的类的实例则返回True,否则返回False)。
class ParentClass: #父类
def method1(self):
print("method1")
class ChildClass(ParentClass): #子类
def method2(self):
print("method2")
myclass=ChildClass()
myclass.method1() #Output:method1
myclass.method2() #Output:method2
print(issubclass(ChildClass,ParentClass)) #Output:True
print(ChildClass.__bases__) #Output:(<class '__main__.ParentClass'>,)
print(ParentClass.__bases__) #Output:(<class 'object'>,)
print(isinstance(myclass,ChildClass)) #Output:True
issubclass函数和isinstance函数检测到存在间接的关系也会返回True。
5.多继承
如果多个父类中有相同的成员,例如有两个或以上父类中有同名的方法,那么会按着父类书写的顺序继承,先继承的父类同名方法会覆盖后继承的,即写在前面的父类会覆盖写在后面的父类同名的方法。
Java、C#等语言中,如果方法名相同而参数个数和数据类型不同,也会认为是不同的方法,这叫做方法的重载。不过由于python是动态语言,所以python类中不会根据方法参数个数和数据类型进行重载。
class Parent1:
def method1(self):
print("method1")
class Parent2:
def method2(self):
print("method2")
class Parent3:
def method2(self):
print("method3")
class MyClass(Parent1,Parent2,Parent3):
pass #如果类中没有任何代码要加pas语句
m=MyClass()
m.method2() #Output: method2
6.接口
接口其实就是一个规范,指定了一个类中都有哪些成员。
python中并没有如Java、C#这些语言的接口的语法。如果要使用接口,就直接使用对象好了,保险起见可以在调用对象成员之前可以使用hasattr函数或getattr函数判断成员是否属于对象。
①hasattr函数
hasattr(对象,“name”),如果成员在对象中存在返回True,否则返回False。
②getattr函数
getattr(对象,“name”,默认值),如果成员在对象中不存在返回第3个参数指定的默认值。
③setattr函数
setattr(对象,“name”,"new value),如果对象中有name属性,则更新该属性的值,如果没有name属性,则会添加一个新的name属性。
class MyClass: #父类
def method1(self):
print("method1")
def method2(self):
print("method2")
def default(self):
print("default")
my=MyClass()
if hasattr(my,'method1'):
my.method1() #Output:method1
else:
print("method1方法不存在")
method=getattr(my,'method2',my.default)
method() #Output:method2
method=getattr(my,'method3',my.default)
method() #Output:default
def method():
print("动态添加的method3")
setattr(my,'method3',method)
my.method3() #Output:动态添加的method3