学习记录~~~部分(学习ing~)
定义:类(抽象的概念): 拥有着相同的特征(属性)和行为(方法)。
简单创建:
类名的命名规则:大驼峰写法(每个单词的首字母大写)
class关键字创建
类的简单创建,
class DogCat(object): # 类名的命名规则:大驼峰写法(每个单词的首字母大写) pass
类属性:
class Student(object): # 类属性 class_name = "8班" student_num = 30
这里创建了一个学生类后,又赋予了班级名和学生人数这个两个属性。而他们就是类属性。
class Student(object): # 类属性 class_name = "8班" student_num = 30 # 方法一 # 直接通过: 类名.类属性 print(Student.student_num) # 方法二 # 先实例化对象,通过:实例对象.属性 来查找 s = Student() print(s.student_num)
在上面代码中的方式二:它先实例化对象,通过:实例对象.属性 来查找,但是实例化对象的空间里没有student_num 这个属性,它就会继续在类空间里去找(或者去它继承的类里找)。
class Student(object): # 类属性 class_name = "8班" student_num = 30 name = "土狗" # 类属性的修改 : 类名.属性名 ,如果没该属性就新建属性;如有,就修改它 Student.name = "憨猫" # 修改 Student.age = 100 # 新建 print(Student.name) print(Student.age)
直观结果:
定义的类只有进行实例化,也就是使用该类创建对象之后,才可以利用。
class Student(object): # 类属性 class_name = "8班" student_num = 30 s = Student() # 实例化对象
当我们需要多个实例对象的时候,第一种方法就会造成代码的冗余,因此就有了__init__方法的作用了。
来个例子看看:
class Student(object): # 类属性 name = "华子" # 方法 def __init__(self, name, age): # 形参,接收实参的传入 self.name = name # 对于这里的参数,前面的name是我们可以再自定义的,而后面的name是不可以变的,因为它要与我们的新参保持一致,就相当于函数里的传参 self.age = age def eat(self): print('华子在吃饭') s1 = Student('土狗', '18') # 实参 ,参数的多少都可以自定义 s2 = Student('憨猫', '19') s3 = Student('猪猪侠', '20') print(s1.name) print(s2.name) print(s3.name) print(s1.age)
看看运行结果:
这里注意的是,Student()实例化后才会赋值给 s1 等变量,而Student()实例化的时候它会自动的触发__init__方法,而我们又可以认为self就是s1,因为下图:
这里打印出了self和s1的id值,发现他们是相同的~~~所以,self就是s1,而self.属性名就是s1.属性名,self.属性名就是在向 s1 这个实例空间里创建实例属性。再就是这里的实参与形参的传入与接收,它是和函数的实参与形参相似的。
class Student(object): # 类属性 class_name = "8班" student_num = 30 name = "土狗" s = Student() s.name = '华仔' s.age = 18 print(s.name) # 查找name属性时,发现类空间和实例空间都有name属性, # 但实例对象会优先在自己空间去查找
运行结果:
所以会有:
class Student(object): # 类属性 name = "华子" def eat(self): print('华子在吃饭') def sleep(self): print('华子要睡觉') s = Student() print(s.name) # 对象调用属性 s.eat() # 调用方法
运行结果:
有self的方法就是实例方法,但是self这个名字并不是不变的,它可以是其他值,但规范习惯用self了,
self表示当前对象
class Student(object): # 类属性 class_num = 30 class_name = '8班' # 方法 def __init__(self, name, course): self.name = name self.course = course def listen(self): print('%s在听%s课' % (self.name, self.course)) # self 中有name,course def homework(self): print('%s在写%s课作业' % (self.name, self.course)) s1 = Student('华仔', 'python') # 实参传入 s1.listen() s2 = Student('我', 'python') s2.homework()
在上面的代码中:s1.listen() ,这个调用方法,解释器会将 s1 这个对象作为实参传给该方法的第一个形参(self).
代码:
class Sum(object): @staticmethod def add(x, y): # 这里是没有self这个参数的 return x + y # 实例对象调用静态方法: s = Sum() print(s.add(2, 6)) # 类对象调用静态方法: print(Sum.add(6, 6))
运行结果:
代码:
class Sum(object): # 类属性 num = 30 @classmethod def add_num(cls): # 这里加了 @classmethod 后,解释器会自动加上 cls 这个参数。 print(id(Sum), id(cls)) cls.num += 1 Sum.add_num() print(Sum.num)
结果:
在上面发现:参数cls与Sum类的地址相同。所以cls就是当前的类对象。Sum这个类对象作为cls的接收者。
继承:是子类复用父类的属性和方法的机制。在Python中,新建的类可以继承一个或多个父类。注意:object 是 Python 中所有类的根类。
单继承:子类之继承一个父类,被称为单继承。
多继承:子类可以拥有多个父类,并且具有所有父类的属性和方法。
代码:
简单例子:
class Animal(object): def eat(self): print('吃') def sleep(self): print('睡') class Dog(Animal): # 继承 Animal 父类 def bark(self): print('狂吠') class Cat(Animal): def climetree(self): print('爬树') s1 = Dog() s2 = Cat() s1.eat() s2.sleep()
结果:
子类没有的属性可以到他继承的父类里去找。
代码:
class Animal(object): def eat(self): print('吃') def sleep(self): print('睡') class Dog(Animal): # 继承 Animal 父类 def bark(self): print('狂吠') def sleep(self): print('睡睡睡睡。。。。。') # 虽然继承了父类的sleep,但子类写了个sleep方法,就覆盖了,但对父类不影响 class Cat(Animal): def climetree(self): print('爬树') s1 = Dog() s1.sleep() s2 = Cat() s2.sleep()
运行结果:
class Animal(object): def __init__(self): self.parent = '我是父类' print(id(self)) print('父类') def sleep(self): print('我是父类的睡') class Dog(Animal): # 继承 Animal 父类 def sleep(self): super(Dog, self).sleep() # super 会首先找到 Dog 的父类(就是类 Animal),然后把类Dog的对象(s)转换为类Animal的对象(self),因为他们的id值相同 print('我是子类的睡睡睡睡。。。。。') print(self.parent) # 找到父类的parent属性 d = Dog() # 别忘了,它会找__init__方法 d.sleep() print(id(d))
运行结果:
注意:super 会首先找到 Dog 的父类(就是类 Animal),然后把类Dog的对象(s)转换为类Animal的对象(self),因为他们的id值相同
class Parent(object): def __init__(self): self.parent = '我是父类' print(id(self)) print('父类') def bar(self): print("我是父类的bar") class Child(Parent): def __init__(self): # super(Child,self) 首先找到 Child 的父类(就是类 Parent),然后把类Child的对象(s)转换为类Parent的对象(self),他们的id值相同。 super().__init__() # super(Child, self).__init__() print('子类') def bar(self): super().bar() # super().bar(message) print('我是子类的bar') print(self.parent) # Child的对象(s)已经转换为类Parent的对象(self) s = Child() # 实例化 Child 对象 s.bar() # 调用s的bar方法 print(id(s))
运行结果:
super().init() # 也可以写成: super(Child, self).init() 。
代码:
class Animal(object): def eat(self): print('吃') class Fly(object): def fly(self): print('飞') class Dog(object): pass class BigBird(Animal, Dog, Fly): pass class LittleBird(Fly, Animal): pass b = BigBird() b.fly() c = LittleBird() c.fly()
运行结果:
对于多个类的继承时,子类继承是有顺序的:从左向右继承
再就是:
print(type(b)) print(type(c))
结果
print(isinstance(b, BigBird)) print(isinstance(b, Fly)) print(isinstance(b, LittleBird))
运行结果:
print(dir(b)) print(c.__dir__())
结果
他们返回的顺序不同,但内容是一样的。~~~~
print(c.__dict__)
运行结果:
注意的是:在dir(object)中,它相当于只是拿出了key,在object__dict__ 中它将 key 和 value都拿出来了。