类及对象初体验
一、类创建
class Animal: def setName(self,name): self.name=name def getName(self): return self.name #创建动物猫的对象 cat=Animal() cat.setName("cat") #调用cat对象的属性name print(cat.name) #调用cat方法的getName方法 print(cat.getName()) #调用cat方法的getName方法 另一种方式 print(Animal.getName(cat))
- 类的创建使用关键字class定义,类名跟在class之后
- 类中的方法就是函数
- 每一个方法中的第一个参数都是self,如果方法中有多个参数,第一个参数将作为self参数使用,在调用方法时,这个参数不用自己传入,系统会将方法所属的对象传入这个参数。
- 调用对象方法的方式有两种,一种是直接通过对象调用;另一种是通过类调用,并且传入相应的对象。
二、方法的私有化
在Java这类语言中提供了private关键字,进行方法或者变量的私有化,但是在python中并没有提供,不过可以使用其它方式来达到这种效果,在python类的方法名前面加上“__”,可以杜绝外部访问这个类中的方法。
class FOO: def f1(self): return "我是f1" def __f2(self): return "我是f2" #类的内部是可以调用私有方法的 def f3(self): return self.__f2() f=FOO() f.f1() f.__f2() #AttributeError: 'FOO' object has no attribute '__f2'
可以看到f2是私有方法,类外部不能进行访问,否则会抛出异常,而在类的内部是可以调用私有方法的。
f2是否是真的在类外部不能调用了呢?当然不是,实际上python编译器遇到"__"开头的方法会将方法名变成“_ClassName__MethodName”,照着这种形式调用,是可行的。
... print(f._FOO__f2())#我是f2 ...
另外,如果想查看类中的所有方法,应该如何做呢?
import inspect methods=inspect.getmembers(f,predicate=inspect.ismethod) print(methods)#[('_FOO__f2', <bound method FOO.__f2 of <__main__.FOO object at 0x0000000000676F28>>), #('f1', <bound method FOO.f1 of <__main__.FOO object at 0x0000000000676F28>>), #('f3', <bound method FOO.f3 of <__main__.FOO object at 0x0000000000676F28>>)]
三、类的继承
类的继承就是一个类从另一个类中获得所有的成员,父类的成员可以在子类中使用。新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。
class A: pass class B: pass class C(A): #单继承 C是派生类,A是基类 pass class D(A,B):#多继承,继承多个类,中间以逗号分隔开 pass
D类中会按照从左到右的顺序继承A类、B类中的成员,如果多个父类中有相同的成员,会按照父类书写的顺序继承,也就是说前面的父类会覆盖写在后面父类同名的方法。
四、检测继承关系
有时需要判断类与类之间是否有继承关系,这样可以利用父类中的方法,那么这种继承关系应该如何判断呢?可以使用issubclass函数进行判断,它接收2个参数,第一个是子类,第二个是父类,如果是继承关系返回True,否则返回False,间接的继承关系也是适用的。
class Fruits: pass class Apple(Fruits): pass print(issubclass(Apple,Fruits))#True
如果获取已知类的父类们,可以直接使用"__bases__",这是类的一个特殊属性
class Fruits: pass class Apple(Fruits): pass print(Apple.__bases__)#(<class '__main__.Fruits'>,)
五、类、类成员、对象的判断
a、hasattr()
判断对象或者类中是否存在某个成员
class Bar: def f1(self): pass b=Bar() print(hasattr(b,"f1"))#True print(hasattr(Bar,"f1"))#True
b、getattr()
获取类中或对象中成员的值,它有三个参数第三个参数用于制定默认值
class Bar: def f1(self): pass b=Bar() print(getattr(Bar,"f1"))#<function Bar.f1 at 0x0000000000535BF8>
c、setattr()
用于设置对象中成员的值,setattr函数有三个参数,前两个与getattr相同,第三个参数用于指定成员的值
#如果对象中有name属性,则更新该值,如果没有,会添加一个新的name属性,也可以更新或者添加类属性 setattr(b,"name","bright") print(b.name)#bright
动态添加函数
class Bar: def f1(self): pass b=Bar() ####类添加f2函数#### def f2(): print("动态添f2") setattr(Bar,'f2',f2) Bar.f2() #类调用 ####对象添加f2函数### def f2(): print("动态添f2") setattr(b,'f2',f2) b.f2() #对象调用
d、isinstance
用于判断实例和类之间的关系
class A: print("A") class B(A): print("B") a=A() b=B() print(isinstance(a,A))#True print(isinstance(b,A))#True
六、多态
同类对象的多种形态,应用多态增加了程序的灵活性、扩展性。
实现多态的步骤:
- 定义新的子类
- 重写对应的父类方法
- 使用子类的方法直接处理,不调用父类的方法
class Animal: def eat(self): pass def run(self): pass class Dog(Animal): def run(self): pass
简单的来说,Dog是新定义的子类,不想调用父类的run方法,需要执行自己的run方法,这就是多态,一个类产生的多个对象,调用同一个方法,产生不同的执行结果。