一. 类和实例
在Python中,定义类是通过class关键字,后面紧接着类名和父类,创建实例是通过类名+()实现,访问限制可以通过__属性以及get和set方法实现
class Student(object): #构造方法 def __init__(self, name, score): self.__name = name self.__score = score # setter方法 def set_name(self, name): self.__name = name def set_score(self, score): self.__score = score # getter方法 def get_name(self): return self.__name def get_score(self): return self.__score # toString def print_score(self): print('姓名 = %s ,分数 = %s' % (self.__name, self.__score)) # 实例化对象 jia = Student('张甲',100) print(jia.get_name()) # 张甲 jia.print_score() # 姓名 = 张甲 ,分数 = 100
二. 继承和多态
子类继承父类,就获得了父类的全部功能,当子类和父类都存在相同的r方法时,子类的方法会覆盖父类的方法,也就是多态
class Animal(object): def run(self): print("动物会跑") class Dog(Animal): def run(self): #覆盖父类,称谓多态 print('狗会跑') pass class Cat(Animal): pass def run2(animal): animal.run() dog = Dog() dog.run() # 狗会跑 run2(Dog()) #传入狗的实例,输出:狗会跑 run2(Animal()) #传入动物的实例,输出:动物会跑
以上面的代码为例,对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了。
三. 获取对象信息
1. 可以使用type()函数判断对象类型,type返回对应的Class类型
print(type(123)) # <class 'int'> x = 123 print(type(x)) # <class 'int'> print(type(x) == type(123)) #True
2. 使用types模块中定义的常量可以判断一个对象是否是函数
import types def fn(): print("Hello") print(type(fn)) #<class 'function'> print(type(fn) == types.FunctionType) #True print(type(abs) == types.BuiltinFunctionType) #True print(type(lambda x:x) == types.LambdaType) #True print(type((x for x in range(10)))==types.GeneratorType) #True
3. 判断class的类型,用type()不方便,所以我们总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。
class Animal(object): def run(self): print("动物会跑") class Dog(Animal): def run(self): #覆盖父类,称谓多态 print('狗会跑') pass class Husky(Dog): def run(self): # 覆盖父类,称谓多态 print('我是哈士奇') pass a = Animal() b = Dog() c = Husky() print(isinstance(a,Animal)) #True print(isinstance(b,Dog)) #True print(isinstance(c,Dog)) #True
4. isinstance()还可以判断一个变量是否是某些类型中的一种
print( isinstance([1, 2, 3], (list, tuple))) #True
5. 如果要获得一个对象的所有属性和方法,可以使用dir()函数,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态。
class Dog(object): def __init__(self, name, age): self.name = name self.age = age def run(self): #覆盖父类,称谓多态 print('狗会跑') pass print(dir(Dog)) ''' ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'run'] ''' d = Dog("嘎嘎",1) print(hasattr(d,'name')) # True print(hasattr(d,'names')) # False if(hasattr(d,'name')): d.name = "哈哈" # 只有在不知道对象信息的时候,我们才会去获取对象信息 print(getattr(d,'name')) #哈哈 print(getattr(d,'names','默认值')) # 默认值 # print(getattr(d,'names')) # AttributeError错误 print(getattr(d,'run')) # <bound method Dog.run of <__main__.Dog object at 0x0000018BD8B6FB80>> getattr(d,'run')() #获得对象的方法,输出:狗会跑
四. 实例属性和类属性
一个类可以有实例属性和类属性,给实例绑定属性的方法是通过实例变量,或者通过self变量
class Dog(object): def __init__(self, name): # 方法一:通过self变量 self.name = name d = Dog("狗命") d.age = 1 # 方法二:通过实例变量 print(d.name,d.age) # 狗命 1
直接在class中定义属性,这种属性是类属性,归类所有,但类的所有实例都可以访问到
class Dog(object): name = "默认" d = Dog() print(d.name) # 默认 d.name = "大狗" print(d.name) # 大狗 print(Dog().name) # 默认
千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性
其他
在评论区看到了一个很好的问题和很好的回答:
老婆说啥都是对的:大神解释下,Animal.run和Animal().run 有什么区别?
用户6553322904:永远记住,类只是一个模板,模板是不会亲自下海干活的。python中如果不加括号,除了个别的,那就是个标识符(你可以理解为变量)。加了括号代表运行前面的东西,比如f就是个标识符,f()代表运行f。Animal(). run,如果Animal是个类,就代表先运行Animal这个类,记得前面章节说的,类运行变为实例,实例才能亲自下海干活。Animal(). run就是这个实例里的run函数(run没加括号表示没运行run,仅仅是个函数而已),Animal(). run()就是先运行Animal生成一个实例,然后运行这个实例里的run函数。你可以试一下Animal. run()也就是运行Animal这个类里的run函数,会报错,告诉你缺少self,这个self是什么呢?就是你创建的实例。再回想一遍前面所说的,类只是个模板,打个比方,网站上的PPT模板怎么能干活呢,你得把它下载下来变成你的实例才能干活。而继承是什么呢,差不多就是,有人把PPT模板复制到另一个PPT模板中,变成了一个新模板(注意是模板)。而拿你的实例做一些东西,比如Animal().run(),或者a=animal();a. run(),就像是在给别人展示你的ppt(不是模板,网上ppt模板怎么能给别人展示呢?),你也可以稍加修改你的ppt(不是修改ppt模板),比如a. eye=blue。
请登录之后再进行评论