1.类定义
语法格式如下:
class ClassName: <statement-1> . . . <statement-N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
2.类对象
类对象支持两种操作:属性引用和实例化。
属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name
类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
class Myclass: i = 123 def f(self): return 'hello world' # 实例化类 x = Myclass() # 访问类的属性和方法 print(x.i) # 123 print(x.f()) # hello world
类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用
如下实例化类 MyClass,对应的 __init__() 方法就会被调用:
class Myclass: i = 123 def __init__(self): print("我是类的构造方法!") def f(self): return 'hello world' # 实例化类 x = Myclass() # 访问类的属性和方法 # 我是类的构造方法! print(x.i) # 123 print(x.f()) # hello world
当然, __init__() 方法可以有参数,参数通过 __init__() 传递到类的实例化操作上,相当于java中的有参构造
self代表类的实例,而非类🙌
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self
class Test: def prt(self): print(self) print(self.__class__) t = Test() # <__main__.Test object at 0x00000213E6693730> t.prt() # <class '__main__.Test'>
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类😊
3.类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例
以下是一个常见类的示例:
class People: # 定义基本属性 name = '' age = 0 # 定义私有属性 __weight = 0 # 构造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w # 类中的普通方法 def speak(self): print('{}说,我今年{}岁'.format(self.name, self.age)) # 实例化类 p = People('dahe', 10, 70) p.speak() # dahe说,我今年10岁
4.继承
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。派生类的定义如下所示:
class DerivedClassName(BaseClassName): <statement-1> . . . <statement-N>
子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内
单继承
以下是一个单继承示例:
class People: # 定义基本属性 name = '' age = 0 # 定义私有属性 __weight = 0 # 构造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w # 类中的普通方法 def speak(self): print('{}说,我今年{}岁'.format(self.name, self.age)) ''' 继承父类的子类 ''' class Student(People): grade = '' def __init__(self, n, a, w, g): # 调用父类的构造函数 People.__init__(self, n, a, w) self.grade = g # 覆写父类的方法 def speak(self): print('{}说,我今年{}岁了,我在读{}年级'.format(self.name, self.age, self.grade)) s = Student('dahe', 20, 50, 3) s.speak() # dahe说,我今年20岁了,我在读3年级
多继承
Python同样有限的支持多继承形式。多继承的类定义形如下例:
class DerivedClassName(Base1, Base2, Base3): <statement-1> . . . <statement-N>
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法😊
慎用多继承❌
5.方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,这个上面已经演示过了
super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
以下是 super() 方法的语法:
super(type[, object-or-type])
参数
type – 类。
object-or-type – 类,一般是 self
super()使用示例:
class A: def add(self, x): y = x + 1 print(y) class B(A): def add(self, x): super().add(x) b = B() b.add(2) # 3
6.组合
不到必要的时候不使用多重继承。哎呀,这可让大家烦恼死了,就像我们有了乌龟类、鱼类,现在要求定义一个类,叫水池,水池里要有乌龟和鱼。用多重继承就显得很奇怪,因为水池和乌龟、鱼是不同物种,那要怎样才能把它们组合成一个水池的类呢?
在Python里其实很简单,直接把需要的类放进去实例化就可以了,这就叫组合:
class Turtle: def __init__(self, x): self.num = x class Fish: def __init__(self, x): self.num = x class Pool: def __init__(self, x, y): self.turtle = Turtle(x) self.fish = Fish(y) def print_num(self): print("水池里面有乌龟 %d 只,鱼儿 %d 只" % (self.turtle.num, self.fish.num)) pool = Pool(1, 5) pool.print_num() # 水池里面有乌龟 1 只,鱼儿 5 只
7.类和对象相关的一些BIF
issubclass(class, classinfo)
如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False
class A: pass class B(A): pass class C: pass print(issubclass(B, A)) # True print(issubclass(B, B)) # True print(issubclass(B, object)) # True print(issubclass(B, C)) # False
isinstance(object, classinfo)
如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False
class A: pass class B(A): pass class C: pass b1 = B() print(isinstance(b1, B)) # True print(isinstance(b1, C)) # False
hasattr(object, name)
hasattr()函数的作用就是测试一个对象里是否有指定的属性。
第一个参数(object)是对象,第二个参数(name)是属性名(属性的字符串名字)
class B: pass b1 = B() print(hasattr(b1, 'x')) # False
getattr(object, name[, default])
返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数)的值;若没有设置default参数,则抛出ArttributeError异常
class A: def __init__(self, x=521): self.x = x a = A(1314) print(getattr(a, 'x')) # 1314
setattr(object, name, value)
与getattr()对应,setattr()可以设置对象中指定属性的值,如果指定的属性不存在,则会新建属性并赋值
class A: def __init__(self, x=521): self.x = x a = A() setattr(a, 'x', 1314) print(getattr(a, 'x')) # 1314
delattr(object, name)
与setattr()相反,delattr()用于删除对象中指定的属性,如果属性不存在,则抛出AttributeError异常
class A: def __init__(self, x=521): self.x = x a = A() delattr(a, 'x') print(hasattr(a, 'x')) # False