Python入门学习(六)高级部分:面向对象
一、类的定义和实例化
#类最基本的作用就是封装代码 #类名第一个字母要大写,多单词组合的类名可以通过每个单词首字母都大写 #类的定义体中可以定义变量(类中一般称为数据成员),也可以定义函数(类中一般称为方法) #类中方法定义时使用类的变量需要通过self引用变量 #要使用类,需要先实例化一个类的对象 #尽量不要在一个模块内既定义类,又创建类的实例 class Student(): name = "" age = 0 def print_file(self): print('name: ' + self.name) print('age: ' + str(self.age)) def StudentHomework(): homework_name = "" # 一般类的定义归集于一个模块内,类的调用、创建归集于另外一个模块内 #student = Student() #实例化 #student.print_file() #调用对象的方法
from c901 import Student student2 = Student() student2.print_file()
二、类变量和实例变量
class Student(): name = "未命名" age = 0 def __init__(self, name, age): name = name age = age def do_homework(self): print("Doing homework...") student1 = Student("石敢当", 18) print(student1.__dict__) #此时输出为空字典,会继续去类变量里查询同名变量
class Student(): name = "未命名" #类变量 age = 0 #构造函数 def __init__(self, name, age): self.name = name #实例变量 self.age = age student1 = Student("lihua", 12) student2 = Student("liudawei", 13) student3 = Student("huoyizheng", 11) print(student1.name) #打印实例变量 print(student2.name) print(Student.name) #打印类变量
如上代码,对于Student这个类,在类定义中设置姓名、年龄这样个体化属性的类变量显然是不大合适的,虽然语法上没有问题。
所以实际使用中最好利用好类变量和实例变量的区别,比如类变量一般用于针对类的整体性的。
#模板 class Student(): #学生数量计数器 sum = 0 name = "未命名" age = 0 #构造函数__init__() #类的实例方法必须显性标识出self #self代表的是实例,而非类 def __init__(self, name, age): #对象初始化 self.name = name self.age = age print(self.name) #打印实例变量 print(name) #虽然与加self打印输出一样,但本质不一样,这里不加self实质打印的是形参对应的参数 print(self.age) #所以要使用实例变量,尽量加上self print(Student.name) #打印类变量 print(self.__class__.name) #打印类变量的另一个方法 Student.sum += 1 #修改类变量 #行为 与 特征 def do_homework(self): print("Doing homework...") student1 = Student("石敢当", 18) print(Student.sum)
三、类方法
类方法的定义必须显式的使用@method标识,且需要cls参数关键字。
#模板 class Student(): #学生数量计数器 sum = 0 #构造函数__init__() #类的实例方法必须显性标识出self #self代表的是实例,而非类 def __init__(self, name, age): #对象初始化 self.name = name self.age = age #类方法的定义,必须使用cls标识且必须用@classmethod标记 @classmethod def plus_sum(cls): cls.sum += 1 print(cls.sum) student1 = Student("石敢当", 18) Student.plus_sum() student2 = Student("喜小乐", 19) Student.plus_sum() student3 = Student("哈哈恰", 18) Student.plus_sum()
四、静态方法
#静态方法的定义,必须使用@statusmethod标记 #类和实例对象都可以调用 #静态方法也可以直接调用类变量 @staticmethod def add(): print(Student.sum) #可以访问类变量 print("This is a static method.") student1 = Student("石敢当", 18) Student.add() #可以通过类去调用静态方法 student1.add() #也可以通过实例对象去调用
但python中静态方法一般不具备类的特殊性质,如self对实例的引用等等,故不常用。
五、成员可见性:公开和私有
成员即是指变量和方法。如果一个类的变量或方法是公开的,则可以在类的外部直接访问;若是私有的,则在外部无法访问。
Python中若要定义类的变量或方法为私有的,需要在变量和方法名之前加“__”,如__name,但不能前后都加即__name__。
#模板 class Student(): #学生数量计数器 sum = 0 #构造函数__init__() #类的实例方法必须显性标识出self #self代表的是实例,而非类 def __init__(self, name, age): #对象初始化 self.name = name self.age = age #实例对象变量score作为敏感数据,避免被直接修改,设为私有 self.__score = 0 print("一个新的实例对象已创建完成!") self.__class__.plus_sum() #调用类方法 print("目前总共有"+str(self.__class__.sum)+"个实例对象!") #类方法的定义,必须使用cls标识且必须用@classmethod标记 @classmethod def plus_sum(cls): cls.sum += 1 print(cls.sum) def set_score(self, score): if score < 0: print("分数不能小于0") self.__score = score print(self.__score) def print_score(self): print(self.__score) student1 = Student("清泉水", 18) student2 = Student("小诺", 19) student1.set_score(90) student2.set_score(82) #以下语句却可以执行,是为什么呢? student1.__score = 9 print(student1.__score) #这里实际上并不是直接访问了实例对象的私有变量 #而是第一句赋值语句给实例对象新增了一个新变量(属性) #可以通过以下查询成员发现 print(student1.__dict__) #其中有_Student__score对应原先的私有变量 #其中__score对应赋值语句新增的属性变量 #其实也就是说,我们还是有方法可以读取私有变量的,如下 print(student1._Student__score, student1.__score) print(student2._Student__score) #所以属性数值的读取最好在类定义中提供读取的方法 student1.print_score() student2.print_score()
六、继承
#父类 class Human(): sum = 0 def __init__(self, name, age): self.name = name self.age = age Human.sum += 1 def get_name(self): print(self.name) def do_homework(self): print("This is a parent method!!")
#子类 from c907 import Human class Student(Human): #在类定义参数中设置继承的父类,即可继承 #sum = 0 def __init__(self, school, name, age): self.school = school #如下句代码,子类引用父类构造函数时就必须加上self参数 #否则在子类构造函数引用时会报错,因为缺少self参数 #在一般的创建实例对象的构造函数使用时其实不是直接地用构造函数名去调用的 #而是通过类名()去调用,python里这种调用机制是可以缺省self的 #另外一方面,这种显性的引用父类名去调用父类构造函数的方式如修改很不方便 #Human.__init__(self, name, age) #所以,一般不用上面方式,而用以下方式 #这种方式如类需要更改父类,则在类定义参数中更改即可,不必涉及具体代码 super(Student, self).__init__(name, age) #以下类方法与父类中的方法同名 #且在其中调用了父类中的方法 def do_homework(self): super(Student, self).do_homework() print("doing homework.") student1 = Student("金陵中学", "石头", 17) #子类和父类中出现同名方法时,优先默认为子类方法 student1.do_homework() print(student1.school) print(student1.name) print(student1.age) student1.get_name()
浙公网安备 33010602011771号