Python类

文章目录

    • 类的定义和使用
    • 类的self
    • 类的构造函数
    • 私有函数与私有变量
    • 闭包
    • 装饰器
      • 无参装饰器
      • 带参数的装饰器
      • 类装饰器
        • classmethod
        • staticmethod
        • property
    • 类的继承
      • 类的定义和使用
      • super函数的作用
      • 多重继承
    • 类的多态
    • 类的高级函数

类的定义和使用

class Person (object):
    # 类属性name
    name = 'djk'
    # 类函数dump
    def dump (self):
        # 如果不加self,则获取不到name
        print (f'{self.name} is dumping')
# 实例化一个类
p = Person ()
print (p.name)
p.dump()    
>>djk
>>djk is dumping

类的self

# self是类函数中的必传参数,且必须放在第一个参数位置
# self 是一个对象,代表实例化的变量自身
# self 可以直接通过点来定义一个类变量
# self中的变量与含有self参数的函数可以再类中的任何一个函数内随意调用
# 非函数中定义的变量在定义时可以不用self
class Person (object):
    name = None
    age = None
    
    def run (self):
         print (f'{self.name} is running')
    def jump (self):
         print (f'{self.name} is jumping')
    def work (self):
        self.run()
        self.jump()
    def sleep ():
        print ('sleep')
p = Person ()
p.jump ()

p.name = 'djk'
p.jump ()

# 属性修改只针对实例化的对象,p和p2属于两个不同的实例化
p2 = Person ()
p2.jump ()

# 添加一个属性
p2.top = 199
print (p2.top)
# 和p是不通用的
# print (p.top)
#>>'Person' object has no attribute 'top'
p.work()
# 类中的函数如果不加self,则无法进行调用
# p.sleep()
# >>sleep() takes 0 positional arguments but 1 was given

类的构造函数

class DemoClass:  # 定义一个类
    def __init__(self, name):
        print(name)
 
dc1 = DemoClass("小明")
dc2 = DemoClass("小吴")
>>小明
>>小吴

私有函数与私有变量

# 私有函数与私有变量:无法被实例化后的对象调用的类中的函数与变量
# 类内部可以调用私有函数与变量
# 只希望类内部业务调用使用,不希望被使用者调用
# 在变量或者函数前加两个下横线__,变量或函数后无需添加
class Cat (object):
    # 私有属性
    __cat_type = 'cat'
    def __init__(self, name, sex):
        self.name = name
        self.__sex = sex
    def run (self):
        # 调用私有函数
        result = self.__run()
        print (result)
    # 私有函数
    def __run (self):
        return f'{self.name} run {self.__sex}'
    def dump (self):
        result = self.__dump ()
        print (result)
    def __dump (self):
        return f'{self.__cat_type}{self.name} dump {self.__sex}'

cat = Cat ('sss', 'male')
cat.run()
cat.dump()
>>sss run male
>>catsss dump male

闭包

​ 一句话说就是,在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了。

def outer(x):
    def inner(y):
        return x + y
    return inner

print(outer(6)(5))
-----------------------------
>>>11

​ 如代码所示,在outer函数内,又定义了一个inner函数,并且inner函数又引用了外部函数outer的变量x,这就是一个闭包了。在输出时,outer(6)(5),第一个括号传进去的值返回inner函数,其实就是返回6 + y,所以再传第二个参数进去,就可以得到返回值,6 + 5。

装饰器

  • 也是一种函数

  • 可以接收函数作为参数

  • 可以返回参数

  • 接受一个函数,内部对其处理,然后返回一个新函数,动态增强函数功能

  • 将C函数在a函数中执行,在a函数中可以选择执行或不执行c函数,也可以对c函数的结果进行二次加工处理

​ 装饰器就是一个闭包,装饰器是闭包的一种应用。什么是装饰器呢,简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。使用时,再需要的函数前加上@demo即可。

无参装饰器

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def hello():
    print("hello")

hello()
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello

带参数的装饰器

def logging(level):
    def outwrapper(func):
        #传入的是外围函数对应的参数
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return outwrapper

@logging(level="INFO")
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[INFO]: enter hello()
>>>hello, good morning

​ 如上,装饰器中可以传入参数,先形成一个完整的装饰器,然后再来装饰函数,当然函数如果需要传入参数也是可以的,用不定长参数符号就可以接收,例子中传入了三个参数。

def check_str (func):
    def inner (*args, **kwargs):
        result = func (*args, **kwargs)
        if result == 'ok':
            print ('is ok')
        else:
            print ('not ok')
    return inneris ok

@check_str
def test (data):
    return data

test ('ok')
>>is ok

类装饰器

classmethod

# classmethod:将类函数可以不经过实例化而被直接调用
'''
@classmethod
def func (cls, ...):
    do
参数介绍:cls替代普通类函数中的self变为cls,代表当前操作的是类
'''

如果不进行实例化,直接用类调用类函数是不可以的,如下:

class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
Test.run()
>>TypeError: run() missing 1 required positional argument: 'self'

这时候classmethod派上用场

class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
    @classmethod
    def dump (cls):
        print ('dump')
Test.dump()
>>dump

不能在classmethod的类函数装饰器中调用一个self函数

class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
    @classmethod
    def dump (cls):
        print ('dump')
        cls.run()
Test.dump()
>>run() missing 1 required positional argument: 'self'

可以在普通的self函数中调用classmethod的装饰器函数

class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
        self.dump()
    @classmethod
    def dump (cls):
        print ('dump')
t = Test ('a')        
t.run()
>>run
>>dump

staticmethod

# staticmethod:将类函数可以不经过实例化而被直接调用
#被该装饰器调用的函数不许传递self或cls参数,且无法在该函数内调用其他类函数或类变量
'''
@staticmethod
def func (...):
    do
'''
class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
        self.dump()
    @classmethod
    def dump (cls):
        print ('dump')
    @staticmethod
    def sleep ():
        print ('sleep')
Test.sleep()
>>sleep

可以在普通的self函数中调用staticmethod的装饰器函数

class Test (object):
    def __init__ (self, a):
        self.a = a
    def run (self):
        print ('run')
        self.dump()
        self.sleep()
    @classmethod
    def dump (cls):
        print ('dump')
    @staticmethod
    def sleep ():
        print ('sleep')
t = Test ('a')
t.run()
>>run
>>dump
>>sleep

property

# property:将类函数的执行免去括弧,类似于调用属性
'''
@property
def func (self):
    do
'''
class Test1 (object):
    def __init__ (self, name):
        self.__name = name
    
    @property
    def name (self):
        return  self.__name
t1 = Test1 (name = 'djk')
print (t1.name)

如果要修改property的返回值,使用@func_name__.setter,他是一个装饰器,并且在定义一个函数和原函数名称相同

class Test1 (object):
    def __init__ (self, name):
        self.__name = name
    
    @property
    def name (self):
        return  self.__name
    @name.setter
    def name (self, value):
        self.__name = value
t1 = Test1 (name = 'djk')
print (t1.name)
t1.name = 'ddd'
print (t1.name)
>>djk
>>ddd

类的继承

  • 通过继承基类来得到基类的功能
  • 被继承的类叫做父类或基类,继承者被称作子类
    • 子类拥有父类的所有属性和方法
    • 父类不具有子类自有的属性和方法
  • 代码的重用

类的定义和使用

class Parent (object):
    def __init__ (self, name, sex):
        self.name = name
        self.sex = sex
    def talk (self):
        return f'{self.name} are walking'
    def is_sex (self):
        if self.sex == 'boy':
            return f'{self.name} is a boy'
        else:
            return f'{self.name} is a girl'
class ChildOne (Parent):
    def play_football (self):
        return f'{self.name} is playing football'
class ChildTwo (Parent):
    def play_pingpong (self):
        return f'{self.name} is playing pingong'
c_one = ChildOne ('djk', 'boy')
result = c_one.play_football()
print (result)
result = c_one.talk()
print (result)
c_two = ChildTwo ('ymj', 'girl')
result = c_two.play_pingpong()
print (result)
result = c_two.talk()
print (result)

p = Parent ('father', 'boy')
result = p.is_sex ()
print (result)
'''
result = p.play_football()
print (result)
这是错误的,父类不能调用子类自有的方法
'''

super函数的作用

​ python子类继承父类的方法而使用的关键字,当子类继承父类后,就可以使用父类的方法

class Parent (object):
    def __init__ (self):
        print ('hello i am parent')
class Child (Parent):
    def __init__(self):
        print ('hello i am child')
        super (Child,self).__init__()
c = Child ()
>>hello i am child
>>hello i am parent


# 传值的用法
class Parent (object):
    def __init__ (self, p):
        print ('hello i am parent %s' %p)
class Child (Parent):
    def __init__(self, c, p):
        print ('hello i am child %s' % c)
        super (Child,self).__init__(p)
c = Child ('child', 'parent')
>>hello i am child child
>>hello i am parent parent

多重继承

​ 可以继承多个父类

class Tool (object):
    def work (self):
        return 'tool work'
    def car (self):
        return 'car will run'
class Food (object):
    def work (self):
        return 'food work'
    def cake (self):
        return 'i like cake'
class Person (Tool, Food):
    pass
p = Person()
print (p.car())
print (p.cake())
print (p.work()) #最左边的类先被继承
print (Person.__mro__)

类的多态

​ 同一个功能的多状态变化

class Parent (object):
    def talk (self):
        print ('father talk')

class  brother (Parent):
    def run (self):
        print ('bro run')
    
    def talk (self):
        print ('bro talk')

bro = brother ()
bro.run ()
bro.talk()
father = Parent()
father.talk()

类的高级函数

'''
如果定义了该函数,当print当前实例化对象的时候,会返回该函数的return信息
def __str__ (self):
    return str_type
'''
class Test (object):
    def __str__ (self):
        return "类的描述"
t = Test()
print (t)
>>类的描述


'''
当调用的属性或者方法不存在时,会返回该方法定义的信息
def __getattr__(self, key):
	print (something)
key:调用任意不存在的属性名
'''
class Test (object):
    def __getattr__ (self, key):
        return "这个key:{}不存在".format (key)
t = Test()
print (t.a)
>>这个key:a不存在

'''
拦截当前类中不存在的属性和值
def __setattr__(self,key,value):
	self.__dict__[key] = value
key:当前的属性名
value:当前参数对应的值
'''
class Test (object):
    def __setattr__ (self, key, value):
        if key not in self.__dict__:
            self.__dict__[key] = value
t = Test()
t.name = 'djk'
print (t.name)
>>djk

'''
本质是将一个类变成一个函数
def __call__ (self, *args, **kwargs):
	print ('call will start')
'''
class Test (object):
    def __call__ (self, a):
        print ('call func will start')
        print (a)
t = Test()
t ('hello')
>>call func will start
>>hello

你可能感兴趣的:(Python,python,开发语言)