PYTHON高阶语法

1. 可变参数*Args**Kwargs

https://www.scaler.com/topics/python/args-and-kwargs-in-python/

*args代表的是一组无关键字的可变参数值。**kwargs表示的是一组可变键值对,类似字典参数。当对程序的输入参数不可预知或者扩展性要求很高时,选择可变参数是不错的主意。

*的用法

def multiplyNumbers(*numbers):
    product = 1
    for n in numbers:
        product *= n
    return product

def args_output(*args):
    for arg in args:
        print(arg)

print("product:", multiplyNumbers(4, 4, 4, 4, 4, 4))
args_output(1, "hello", 3.14)

**的用法

def whatTechTheyUse(**kwargs):
    result = []
    for key, value in kwargs.items():
        # result.append("{} uses {}".format(key, value))
        result.append("%s uses %s" % (key, value))
    return result

print(whatTechTheyUse(Google='Angular', Facebook='react', Microsoft='.NET'))

***的拆包操作

Unpacking operators are used to unpack the variables from iterable data types like lists, tuples, and dictionaries.
A single asterisk() is used on any iterable given by Python.
The double asterisk(
*) is used to iterate over dictionaries.

carCompany = ['Audi','BMW','Lamborghini']
print(*carCompany)

techStackOne = {"React": "Facebook", "Angular" : "Google", "dotNET" : "Microsoft"}
techStackTwo = {"dotNET" : "Microsoft1"}
mergedStack = {**techStackOne, **techStackTwo}
print(mergedStack)

2. property属性用法

https://www.liaoxuefeng.com/wiki/1016959663602400/1017502538658208

在python中如果直接通过公有变量的方式把参数对外开放,则调用者可以随便修改参数值。如果通过类似java的get,set方法,则又略显复杂。在python中使用property可以兼容两者的功能,读取值的时候实际使用的是get方法,赋值的时候调用的是set方法。

class Student(object):
    def get_score(self):
        return self._score

    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError("score must be an integer!")
        if value < 0 or value > 100:
            raise ValueError("score must between 0 ~ 100!")
        self._score = value

    def del_score(self):
        del self._score

    score = property(get_score, set_score, del_score)

student = Student()
student.score = 99
print(student.score)
student.score = 102

可以使用装饰器(java中为注解)简化

class Student(object):
    @property
    def score(self):
        return self._score

    # 这里的score要和带有@property注解的方法名对应
    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError("score must be an integer!")
        if value < 0 or value > 100:
            raise ValueError("score must between 0 ~ 100!")
        self._score = value

    @score.deleter
    def del_score(self):
        del self._score

    # score = property(get_score, set_score, del_score)

student = Student()
student.score = 99
print(student.score)
student.score = 102

也可以通过下面的方式自定义(描述符)

class Name:
    def __get__(self, obj, cls=None):
        pwd = input('请输入获取密码')
        if pwd == '123':
            return obj._name
        else:
            print('密码不正确,获取失败')
    
    def __set__(self, obj, value):
        pwd = input('请输入设置密码')
        if pwd == '321':
            obj._name = value
            print('设置成功')
        else:
            print('密码不正确,设置失败')

class Student:
    name = Name()

s = Student()
s.name = '小明'
print(s.name)

3. from __future__ import *的作用

https://blog.csdn.net/zzc15806/article/details/81133045

这样的做法的作用就是将新版本的特性引进当前版本中,也就是说我们可以在当前版本使用新版本的一些特性。主要是为了版本兼容性,python中有个six库是专门用来处理版本兼容问题的。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
#  兼容python2.x
print("hello world")
# 在python2.x版本中值为2,有了上面的导入之后,值和python3.x版本一致都为2.5
print(5/2)

4. 魔法方法 :__getitem__ 、 __len__、__setitem__等的使用

https://www.jianshu.com/p/cca8e8834066

在Python中,如果我们想实现创建类似于序列和映射的类(可以迭代以及通过[下标]返回元素),可以通过重写魔法方法getitemsetitemdelitemlen方法去模拟。当然有很多其他魔法方法,比如__cmp__(self, other),__add__(self, other),参考(https://pyzh.readthedocs.io/en/latest/python-magic-methods-guide.html):,其作用类似于C++的操作符重载。

魔术方法的作用:
getitem(self,key):返回键对应的值。
setitem(self,key,value):设置给定键的值
delitem(self,key):删除给定键对应的元素。
len():返回元素的数量

import collections

Card = collections.namedtuple("Card", ["rank", "suit"])
# 也可以使用一个类来定义Card
# class Card:
#     def __init__(self,rank,suit):
#         self.rank = rank
#         self.suit = suit


class Puke:
    ranks = [str(n) for n in range(2, 11)] + list("JQKA")
    suits = "黑桃 方块 梅花 红心".split()

    def __init__(self):
        self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]

    def __setitem__(self, key, value):
        print(key, value)
        self._cards[key] = value

pk = Puke()
print(len(pk))
print(pk[2:6])
print(pk[12::13])

5. 元类

https://www.geeksforgeeks.org/how-to-create-an-instance-of-a-metaclass-that-run-on-both-python2-and-python3/
https://www.zhihu.com/column/c_1604522311041966081
https://www.liaoxuefeng.com/discuss/969955749132672/1195234549018496

元类是用来动态生产功能类的类,是类验证的高效工具,防止子类继承某些类功能,动态生成类。

from typing import Any


class NoInstance(type):
    # 类实例化
    def __call__(self, *args, **kwargs):
        if len(args) == 0 or args[0] != "factory":
            raise TypeError("Can't instantiate directly")
        # return super().__call__(*args, **kwargs)
        return super().__call__(*(), **kwargs)


class Last_of_us(metaclass= NoInstance):
    def play(self):
        print("the Last Of Us is really funny")


class Uncharted(metaclass= NoInstance):
    def play(self):
        print("the Uncharted is really funny")


class PSGame(metaclass= NoInstance):
    def play(self):
        print("PS has many games")


class GameFactory:
    games = {"last_of_us": Last_of_us, "uncharted": Uncharted}

    def __new__(cls, name):
        if name in cls.games:
            return cls.games[name]("factory")
        else:
            return PSGame()


uncharted = GameFactory("uncharted")
uncharted.play()
last_of_us = GameFactory("last_of_us")
last_of_us.play()
psgame = GameFactory("else")
psgame.play()

你可能感兴趣的:(PYTHON高阶语法)