定义类、创建对象、属性和方法、__init__实例化方法、__new__创建对象的方法、__str__打印对象时自动调用的方法、单继承、多继承、mro()继承链、私有属性和私有方法、__dict__获取属性和方法的方法、类属性、类方法@classmethod、静态方法@staticmethod、多态、单例、动态添加属性和方法、__slots__属性、property装饰器、types.MethodType()方法
# !usr/bin/env python
# _*_coding:utf-8_*_
__author__ = 'Noiccy'
'''
@file: 02-class.py
@time: 2019/01/18
'''
#定义类
class Teacher(object):
#方法
def show(self):
print(id(self))
print('111')
#创建对象
t = Teacher()
#添加属性(动态)
t.name = 'zs'
t.age = 20
print(t.name, t.age)
#修改属性
t.age = 18
print(t.name, t.age)
#不同对象占用不同的内存地址
#self表示:哪一个对象调用的这个方法,self就是谁
t1 = Teacher()
t1.show()
print(id(t1))
t2 = Teacher()
t2.show()
print(id(t2))
#__init__方法
class Teacher1(object):
#对象创建好以后的初始化方法
def __init__(self, name = 'zs', age = 18):
#设置默认属性
self.name = name
self.age = age
print('定义对象下时,自动调用init魔法方法')
def show(self):
print('111')
tt1 = Teacher1(age = 20)
print(tt1.name, tt1.age)
#对象创建流程
'''
1、创建一个对象
2、调用init方法,把对象的引用传给init方法中的self
'''
class Dog(object):
#init并不是创建的方法,init执行时,对象已经创建,用init添加属性
def __init__(self):
print('__init__')
#真正创建对象的方法,cls是当前类
def __new__(cls, *args, **kwargs):
print('__new__')
print(id(cls))
#复写了父类的的new方法
return object.__new__(cls)
d = Dog()
print(id(Dog))
# __str__: 当使用print打印对象时会调用此方法
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "我叫:%s, 年龄:%d" %(self.name, self.age)
person = Person('wang', 20)
print(person)
#继承
#单继承,只有一个父类
class Person(object):
def __init__(self):
self.name = 'zs'
self.age = 18
def show(self):
print(self.name, self.age)
class Student(Person):
pass
#子类可以直接使用父类的属性和方法
stu = Student()
stu.show()
#多继承,可以有多个父类
class A(object):
def show(self):
print('A')
class B(object):
def show(self):
print('B')
class C(A, B):
pass
c = C()
c.show() #A
#调用的顺序,根据类继承的顺序决定
print(C.mro()) #继承链,类去调用继承链
#重写父类方法
class Person1(object):
def eat(self):
print('eat')
class Student1(Person1):
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s eat' % self.name)
stu1 = Student1('wang', 11)
stu1.eat()
#子类调用父类方法
'''
1、使用self直接调用,要看子类里面有没有,如果有,会调用自己,没有的话,根据继承链找
2、使用父类名去调用,需要传一个实例进去,Animal.run(self)
3、supper调用父类的方法
'''
class Animal(object):
def run(self):
print('Animal-run')
class Cat(Animal):
def run(self):
print('猫在跑')
def eat(self):
self.run()
Animal.run(self)
print('eat')
#Cat:根据继承链去找Cat的下一个类
#self:表示实例对象,可以根据这个实例对象找到相应的继承链
super(Cat,self).run()
#获取继承链,self.__class__获取self的当前类
print(Cat.mro())
print(self.__class__.mro()) #使用super拿的不一定是直接继承的类
c1 = Cat()
c1.eat()
#多继承下,子类调用父类的方法
class AA(object):
def show(self):
print('AA')
class BB(object):
def show(self):
print('BB')
class CC(AA, BB):
def show(self):
print(self.__class__.mro())
super(AA, self).show() #BB
print('CC')
cc = CC()
cc.show()
class AAA(object):
def __init__(self, name):
print('AAA')
self.name = name
class BBB(AAA):
def __init__(self, age):
print('BBB')
self.age = age
#调用父类AAA的初始化方法
super(BBB, self).__init__('ls')
#super的简化写法
super().__init__('ls')
bbb = BBB(18)
print(bbb.age, bbb.name)
#私有方法和私有属性
#私有属性只能在类的内部使用
class Person2(object):
def __init__(self, name, age):
self.__name = name
self.__age = age
def set_age(self, new_age):
if new_age>0 and new_age<=100:
self.__age = new_age
else:
self.__age = 0
def show(self):
print(self.__name, self.__age)
pp = Person2('zs', 20)
print(pp._Person2__name)
pp.set_age(3)
pp.show()
#私有属性和私有方法,在类的内部使用,一般不能在类外被调用(Python中没有绝对的私有)
#在类外使用p.__age = 20,print(p.__age)不会报错,相当于动态添加了一个属性
class Person(object):
def __init__(self):
self.__age = 10
def __show(self):
print('私有方法')
class Student(Person):
def show(self):
self.__show() #报错,子类不能直接使用父类的私有属性和私有方法
print(self.__age)#报错
p = Person()
p.__age = 20
print(p.__age)
#获取对象的属性
print(p.__dict__) #{'_Person__age': 10, '__age': 20}
#获取类的属性和方法
print(Person.__dict__)
#类属性和实例属性
#类属性:在类的内部,方法的外部定义的属性
#实例属性:定义在__init__方法中的属性
class Person1(object):
age = 18 #类属性
def __init__(self):
self.name = 'zs' #实例属性
#查看类的属性和方法
print(Person1.__dict__)
#获取类属性
print(Person1.age)
#类名无法访问实例属性(*****)
#print(Person1.name)#报错
#对象可以访问实例属性和类属性(*****)
p = Person1()
print(p.name)
print(p.age)
p.age = 50
print(Person1.age) #18
print(p.age) #50,对象无法修改类属性,这里相当于增加了一个实例属性(*****)
class Tool(object):
num =0
def __init__(self, name):
self.name = name
Tool.num +=1 #类去修改类属性
t = Tool('ls')
t2 = Tool('zs')
t3 = Tool('ww')
print(Tool.num)
#类方法和静态方法
class Person2(object):
num = 10 #类属性
__sex = 'man' #私有类属性,外界不可以使用
def __init__(self):
self.name = 'zs'
#实例方法
def show(self):
print('show')
#类方法,系统提供的装饰器,出现类属性时,尽量使用类方法调用
@classmethod
def show_info(cls): #cls表示当前类
print('show_info')
print(id(cls))
#静态方法,和当前对象和类没有关系
@staticmethod
def show_msg():
print('show_msg')
#类方法可以通过类和实例调用
Person2.show_info()
print(id(Person2))
p2 = Person2()
p2.show_info()
#通过类名调用实例方法,需要传参(必须传入当前类的实例)
Person2.show(p2)
#可以通过类名和实例对象调用静态方法
Person2.show_msg()
p2.show_msg()
import types
'''
#多态,多态就是一种调用方法的技巧,不会影响类的内部设计
#优点:增加代码的灵活性
#多态指事物的多种形态
'''
class Animal(object):
def run(self):
print('Animal-run')
class Dog(Animal):
def run(self):
print('Dog-run')
class Cat(Animal):
def run(self):
print('Cat-run')
#只要传入像Animal类的
def show(animal):
animal.run()
dog = Dog()
cat = Cat()
print(isinstance(dog, Dog))
print(isinstance(cat, Cat))
print(isinstance(dog, Animal))
show(dog)
show(cat)
'''
#单例(单个实例):在程序中不管根据一个类创建了多少次对象,只能创建一个实例
#多个对象指向相同的内存地址
'''
class Person(object):
#私有类属性
__instance = None
#实例化
def __init__(self, name, age):
self.name = name
self.age = age
#创建对象
def __new__(cls, *args, **kwargs):
if cls.__instance == None:
print('创建一个对象')
cls.__instance = object.__new__(cls)
return cls.__instance
#创建对象函数__new__只调用了一次
p = Person('zs', 18)
p2 = Person('ls',20)
print(id(p))
print(id(p2))
'''
#Python是动态语言(js、php、Ruby等),运行过程中可以改变其结构的语言
'''
class Person3(object):
num = 100
def __init__(self, name, age):
self.name = name
self.age = age
p3 = Person3('zs', 18)
#动态添加类属性
Person3.num = 3
print(Person3.num)
p3.sex = 'man'
print(p3.__dict__)
#动态添加方法
#第一种(不要使用)
def run(self):
print('run')
p3.run = run
p3.run(p3) #需要传一个引用
#第二种方法:import types
def run_r(self):
print('run_r')
print(self.name)
p3.run = types.MethodType(run, p3)
p3.run()
#动态添加静态方法
@staticmethod
def run_s():
print('run_s')
Person3.run_s = run_s
Person3.run_s()
#动态添加类方法
@classmethod
def run_c(cls):
print('run_c')
print(cls.num)
print(id(cls))
Person3.run_c = run_c
Person3.run_c()
#slot属性,约束实例属性(方法:方法也可以看作属性),对类不起作用
class Person4(object):
__slots__ = ('name', 'age', 'run1')
def __init__(self, name, age):
self.name = name
self.age = age
p4 = Person4('zs',18)
#p4.sex = 'man' #报错
def run1(self):
print('run1')
p4.run1 = types.MethodType(run1, p4)
#slot属性对类属性和方法不起作用
@classmethod
def class_func(cls):
print('class_func')
Person4.class_func = class_func
#property装饰器,将方法改成属性,方便获取和传值
class Student(object):
def __init__(self):
self.__num = 100
@property
def get_num(self):
return self.__num
@get_num.setter
def set_num(self, new_num):
self.__num = new_num
stu = Student()
# print(stu.get_num())
# stu.set_num(200)
# print(stu.get_num())
print(stu.get_num)
stu.set_num = 300
print(stu.get_num)
#property常用写法
class Student2(object):
def __init__(self):
self.__num = 100
@property
def num(self):
return self.__num
@num.setter
def num(self, new_num):
self.__num = new_num
stu2 = Student2()
print(stu2.num)
stu2.num = 400
print(stu2.num)