python 类的成员及继承

1. @staticmethod 静态方法

静态方法不能访问实例变量和类变量,除了身处类里面,所以只能通过类调用以外,它其实和类没有什么关系。如果想要用它访问实例变量或类变量,需要把实例和类传递给函数。

class People(object):
    def __init__(self,name):
        self.name = name

    @staticmethod       # 静态方法,不能访问实例变量和类变量,和类实际没啥关系,除了把它放到类里面,然后通过类来调用它。
    def getname(self,sex):  # 虽然有self,但是需要调用的时候手动传入实例。
        print('%s is a %s' %(self.name,sex))

people = People('LaoWang')
people.getname(people,'man')  # 想要访问实例变量,只能手动传递实例进入!如果写成:people.getname('man')会报错。

2. classmethod 类方法

类方法只能访问类变量,不能访问实例变量。想要访问实例变量,需要手动传递实例给函数。

class People(object):
    age = 30

    def __init__(self,name):
        self.name = name

    @staticmethod       # 静态方法,不能访问实例变量和类变量,和类实际没啥关系,除了把它放到类里面,然后通过类来调用它。
    def getname(self,sex):  # 虽然有self,但是需要调用的时候手动传入实例。
        print('%s is a %s' %(self.name,sex))

    @classmethod   # 类方法,只能访问类变量,不能访问实例变量,如果要访问实例变量,需要手动传入实例。
    def getage(cls):
        print('age is %s' % cls.age)

people = People('LaoWang')
people.getname(people,'man')  # 想要访问实例变量,只能手动传递实例进入!如果写成:people.getname('man')会报错。
people.getage()

3. @property 属性方法

属性方法,把一个方法变成属性,调用时不加括号即可完成调用,就像调用一个属性一样。

class People(object):
    age = 30

    def __init__(self,name):
        self.name = name

    @staticmethod       # 静态方法,不能访问实例变量和类变量,和类实际没啥关系,除了把它放到类里面,然后通过类来调用它。
    def getname(self,sex):  # 虽然有self,但是需要调用的时候手动传入实例。
        print('%s is a %s' %(self.name,sex))

    @classmethod   # 类方法,只能访问类变量,不能访问实例变量,如果要访问实例变量,需要手动传入实例。
    def getage(cls):
        print('age is %s' % cls.age)

    @property     # 属性方法,把一个方法变成属性。调用时不用加括号。
    def eat(self):
        print('%s is eating.' %self.name)

people = People('LaoWang')
people.getname(people,'man')  # 调用静态方法。想要访问实例变量,只能手动传递实例进入!如果写成:people.getname('man')会报错。
people.getage()                # 调用类方法。
people.eat                     # 调用属性方法。不加括号

属性方法的修改和删除:

class People(object):
    age = 30

    def __init__(self,name):
        self.name = name

    @staticmethod       # 静态方法,不能访问实例变量和类变量,和类实际没啥关系,除了把它放到类里面,然后通过类来调用它。
    def getname(self,sex):  # 虽然有self,但是需要调用的时候手动传入实例。
        print('%s is a %s' %(self.name,sex))

    @classmethod   # 类方法,只能访问类变量,不能访问实例变量,如果要访问实例变量,需要手动传入实例。
    def getage(cls):
        print('age is %s' % cls.age)

    @property     # 属性方法,把一个方法变成属性。调用时不用加括号。
    def eat(self):
        print('%s is eating.' %self.name)
    @eat.setter   # 属性的修改
    def eat(self,food):
        print('This is eat setter: %s' %food)
    @eat.deleter  # 属性的删除
    def eat(self):
        print('eat has been deleted.')

people = People('LaoWang')
people.getname(people,'man')  # 调用静态方法。想要访问实例变量,只能手动传递实例进入!如果写成:people.getname('man')会报错。
people.getage()                # 调用类方法。

people.eat                     # 调用属性方法。不加括号
people.eat = 'suger'          # 调用eat.setter
del people.eat                 # 调用eat.deleter

 4. 其他类成员:

class T(object):
    '''this is doc'''
    def __new__(cls, *args, **kwargs):
        print('this is new func')
        return super().__new__(cls)

    def __init__(self,name):
        self.name = name

    def getname(self):
        print(self.name)

    def __getitem__(self, item):
        print('getitem:',item)

    def __setitem__(self, key, value):
        print('setitem:',key,value)

    def __delitem__(self, key):
        print('delitem:',key)

    def __call__(self, *args, **kwargs):
        print('this is call, you should add bracket')

    def __str__(self):
        return 'you are print obj'

    def __del__(self):
        print('When obj is been destroyed,this func would execution automatically.')


t=T('Wang')       # # T是一个类,它是由type创建的(type是所有类的类,它可以创建类对象,然后类对象可以创建实例)。而type里面定义了一个__call__函数,所以才能使用 'T()'
print(T.__doc__)  # 打印类的文档注释
print(t.__module__)# 打印对象所处的模块名
print(t.__class__) # 打印对象的类
print(t.__dict__)  # 打印对象的变量
print(T.__dict__)  # 打印类的变量
print(t)           # 打印对象,打印__str__方法的返回值(没有str方法,则打印对象的内存地址)
t()         # 对象直接加括号,调用__call__方法
val = t['1']  # __getitem__
t['1'] = 1    # __setitem__
del t['1']    # __delitem__
del t         # __del__

 

5. 类的类

python中万物皆对象。类其实也是一个对象。在python中类可以创建实例,那么类本身又是谁创建的呢,答案是type

num = type(1)
string = type('my')
dictionary = type({1:'1'})
print(num,string,dictionary)
#   
print(num.__class__,string.__class__,dictionary.__class__)
#   

从上面的例子可以看出,数字、字符串、字典,它们的类型都是由不同的类创建的。而这些类再往上追溯,它们又都是由 type 类创建的。所以说,type就是所有类的类。

通过type创建类:

# class A(object):
#     a = 5
#     def abc(self,name):
#         self.name = name
#     def getname(self):
#         print(self.name)

#  使用type创建一个类,和上面的类一模一样
def init(self, name):
    self.name = name
def getname(self):
    print(self.name)
A = type('A',(object,),{'a':5,'__init__':init,'getname':getname})
# type第一个参数:类名
# type第二个参数:当前类的基类
# type第三个参数:类的成员

aa = A('Wang')
aa.getname()
print(aa.a)

 

6. 元类 metaclass

元类就是用来造类的类,type也是一个元类,只不过它是python内建的元类,是所有类的类。我们也可以自己创建一个元类,用来动态的创建类。

class MyType(type):                     # 创建元类,父类需要传入type
    def __new__(cls,name,bases,attrs):   # 第一步,元类的操作都在__new__中完成,第一个参数是将创建的类。name,将要创建的类。bases,将要创建的类的父类。attrs,类的方法和属性的字典
        print("Mytype __new__",name,bases,attrs,sep=' / ')
        print('cls',cls)
        return type.__new__(cls, name,bases,attrs) # 如果返回一个已经存在的实例或者不返回任何值,则init不会被调用

    def __init__(self,*args,**kwargs):  # 第二步,init
        print("Mytype __init__",*args,**kwargs)

    def __call__(self, *args, **kwargs):  # 第三步,创建的类实例化时才执行。类实例化时需要加括号对吧,这个括号就是__call__方法赋予的。
        print("Mytype __call__", *args, **kwargs)
        obj = self.__new__(self)          # Foo类的new方法
        print("obj.... ",obj,*args, **kwargs)
        print(self)
        self.__init__(obj,*args, **kwargs)
        return obj

print('-------------------------------------')

class Foo(object,metaclass=MyType):
    def __new__(cls, *args, **kwargs):
        print("Foo __new__",cls, *args, **kwargs)
        return object.__new__(cls)

    def __init__(self,name):
        self.name = name
        print("Foo __init__")

    def getname(self):
        print('name is ',self.name)

f = Foo("Wang")
print("f",f)
print("fname",f.name)

 

例子:使用元类来创建类,并动态的给所创建的所有类添加一个属性:类名 = 'Hello, '+类名

class Meta(type):      # 元类
    def __new__(cls, name,bases,attrs):  # name,类名。attrs,类的所有方法属性的字典。
        attrs[name] = 'Hello, %s' % name  # 创建一个 类名 的变量,值为 ‘Hello, 类名’
        print(attrs)                  # 打印一下类的方法和属性。
        return type.__new__(cls,name,bases,attrs)

class People(object,metaclass=Meta): # 使用元类来定制类
    age = 22

peo = People()
print(peo.People)

 因为python是一门解释性语言,所以按照从上往下顺序执行

class Meta --> Meta类里面的方法和属性 --> class People --> People里面的方法和属性 --> 注意:此时将People里面的方法和属性传递给元类,执行元类的__new__方法、__init__方法(此例子中没重写) --> peo=People() 实例化 --> 元类的__call__方法(此例子中没重写) --> print(peo.People)

 

7. 其他封装、继承、多态

# 类变量:修改、增加、删除
# 实例变量:增加、删除、修改

# 析构函数 __del__
# 私有变量、私有方法:前面加 __

class Car():
    region = 'China'                 # 类变量,公有变量,每个实例化的对象都可以访问
    def __init__(self,brand,price):  # 构造方法,实例化
        self.brand = brand
        self.price = price
        self.__mile = 100              # 私有变量,只能内部访问,无法通过实例化的对象进行外部访问
    def __modifyMiles(self,mile):    # 私有方法,只能内部调用
        self.__mile += mile
    def getMiles(self):
        return self.__mile
    def __del__(self):              # 析构方法,销毁对象时自动执行的方法(如程序运行结束、主动删除对象)
        # print('destroy obj.')
        pass
    @staticmethod  # @staticmethod是把函数嵌入到类中的一种方式,函数属于类,但是和类没有什么直接关系
    def car_run(obj):  # 接受一个对象作为参数,调用这个参数的方法
        obj.run()

car = Car('奔驰',300000)
car.getMiles()
car.owner = 'LaoWang'  # 实例化的对象也可以在外面直接添加变量
print(car.region)
car.region = 'Beijing' # 相当于重新声明了一个实例化变量
print(car.owner,car.region) # 当类变量和实例化变量同时存在,首先访问实例变量
del car.owner
del car.region
print(Car.region)

class CC():
    pass

class EleCar(Car,CC):  # 多继承,子类继承父类Car,CC;子类不能直接调用父类的私有变量和私有方法,可以调用父类的调用了私有方法的方法
    def __init__(self,brand,price,battery): # 要写父类的参数
        # 三种继承方法,推荐最后一种
        # Car.__init__(self,brand,price)
        # super(EleCar,self).__init__(brand,price)
        super().__init__(brand,price)    # 继承父类,初始化父类的属性(只初始化一个父类,按继承的顺序从左到右查找(广度优先),遇到的第一个带有__init__方法的父类停止)。不管多少个父类,只写一遍即可。
        self.battery = battery
    def run(self):
        print('%s is running.' % self.brand)

class Bike(Car):
    def __init__(self,brand,price):
        super().__init__(brand,price)
    def run(self):
        print('%s is running.' % self.brand)

bike = Bike('永久',300)
bike.run()

print('--------')
ec = EleCar('宝马',300000,'asdf')
# print(ec.getMiles())
ec.run()

print('多态:一个接口,多种实现')
Car.car_run(ec)
Car.car_run(bike)

 

 

 

 

 

你可能感兴趣的:(python 类的成员及继承)