Python基础6:类和对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/plychoz/article/details/86547398

定义类、创建对象、属性和方法、__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)


猜你喜欢

转载自blog.csdn.net/plychoz/article/details/86547398