python 类 和ES6 类的对比

python和ES6来回切换,有时候会把类的写法都搞混了,记录下,方便下次翻一翻记录。


面向对象技术简介:

  • 类(Class)
  • 类变量(静态属性)
  • 数据成员
  • 方法重写
  • 局部变量
  • 实例变量
  • 私有属性
    Python 中,并没有真正意义的私有属性,方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到。(伪私有属性和私有方法)
  • 继承
  • 实例化
  • 方法(实例方法、类方法、静态方法,私有方法)
    静态方法与类方法界限不清晰,都可以访问类,只是不通过cls
  • 对象
  • python的实例可以访问到类方法和静态方法,es6的实例访问不了静态方法
  • 似乎只有python才有类方法 @classmethod

>>ES6 类:

class Auth {
    constructor(level) {
        this.level = level || 1
        Auth.USER = 8
        Auth.ADMIN = 16
        Auth.SUPER_ADMIN = 32
    }

    get m() {
        return async (ctx, next) => {
            
            const userToken = basicAuth(ctx.req)
            let errMsg = 'token不合法'

            if (!userToken || !userToken.name) {
                throw new global.errs.Forbbiden(errMsg)
            }
            try {
                var decode = jwt.verify(userToken.name, 
                    global.config.security.secretKey)
            } catch (error) {
                if (error.name == 'TokenExpiredError'){
                    errMsg = 'token已过期'
                }
                throw new global.errs.Forbbiden(errMsg)
            }

            if(decode.scope < this.level){
                errMsg = '权限不足'
                throw new global.errs.Forbbiden(errMsg)
            }

            // uid,scope
            ctx.auth = {
                uid:decode.uid,
                scope:decode.scope
            }

            await next()
        }
    }

    static verifyToken(token){
        try{
            jwt.verify(token, 
                global.config.security.secretKey)
            return true
        }
        catch (error){
            return false
        }

    }
}

取值函数(getter)和存值函数(setter)
类的方法内部如果含有this,它默认指向类的实例


静态方法:

静态方法包含this关键字,这个this指的是类,而不是实例
父类的静态方法,可以被子类继承
静态方法也是可以从super对象上调用的
静态属性


静态属性:

静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性

Class.propName = '这是静态属性的命名方法一'

class Class{
  static propName = "这是静态属性的命名方法二"
}
// 它们都是声明在原形链上prototype

私有方法 和 私有属性:

私有方法和私有属性,是只能在类的内部访问的方法和属性,外部不能访问
私有方法的约定方法有三种:
第一种为在方法名前加下划线 "_" (私有属性也可以这么约定)
第二种将私有方法移除模块内外,模块内通过call调用
第三种为利用Symbol值的唯一性,将私有方法的名字命名为一个Symbol值 (私有属性也可以这么约定)

(新提案,在属性名和方法名之前,加#表示,如下)
觉得这个方法还是试行阶段。未做到统一,复制阮老师的代码,在node12还会报错

class a1 {
  //私有属性
  #a;

  constructor() {
    this.#a = 'private field';
    this.c = 'c';
  }

  b() {
    console.log(`hello ${this.#a} ${this.c}`);
    this.#c();
    // this.#d();
  }
  // 私有方法
  #c = function(){
    console.log('### c');
  }
  // 语法不正确
  // #d() {
  // console.log('### d');
  // }
}

let cl_a = new a1();
cl_a.b();
// console.log(cl_a.#a);
// console.log(cl_a.#c());

super 关键字:

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

  • 作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。
  • super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

>>python 类:

class User(Base):
    id = Column(Integer, primary_key=True)
    email = Column(String(24), unique=True, nullable=False)
    nickname = Column(String(24), unique=True)
    # 权限等级 普通用户默认为 1
    auth = Column(SmallInteger, default=1)
    _password = Column('password', String(100))

    # 重写模型keys方法
    # dict(对象) 只能拿到对象的实例变量 拿不到类变量 需要通过上述方法该找
    # dict(o) 如果dict传入对象 其会调用对象的keys方法获取key值 然后通过中括号形式o['name']访问变量
    # 默认对象是不可以中括号的形式访问变量 o['name'] 所以要在__getitem__方法通过getattr() 方法获取对象和类的变量
    # 见app/models/user.py
    def keys(self):
        # 一个元素的元组定义需要加逗号 ('name',)
        # 使用列表就不用加逗号 ['name']
        return ['id', 'email', 'nickname', 'auth']

    @property
    def password(self):
        return self._password

    # 用户密码加密
    @password.setter
    def password(self, raw):
        self._password = generate_password_hash(raw)

    # 注册方法
    # 为什么要用静态方法声明?
    @staticmethod
    def register_by_email(nickname, account, secret):
        with db.auto_commit():
            # 因为这里已经实例化了,所以上述要用静态方法,为了符合面向对象写法 ??
            user = User()
            user.nickname = nickname
            user.email = account
            user.password = secret
            db.session.add(user)

    @staticmethod
    def verify(email,password):
        # TODO 这么写好像不能重定义msg内容
        # TOTO 这里如果不传email=email 会默认返回表第一个数据 ?
        user = User.query.filter_by(email=email).first_or_404()
        # user = User.query.filter_by(email=email).first()
        # if not user:
        #     raise NotFound(msg = '没找到该用户')
        if not user.check_password(password):
            raise AuthFailed(msg='没找到该用户,请检查账号密码')
        # return {'uid': user.id}
        scope = 'AdminScope' if user.auth == 2 else 'UserScope'
        return {'uid': user.id, 'scope': scope}

    # raw 是用户传过来的原始密码
    def check_password(self, raw):
        if not self._password:
            return False
        return check_password_hash(self._password, raw)
class APIException(HTTPException):
    code = 500
    msg = 'sorry, we made a mistake (* ̄︶ ̄)!'
    error_code = 999

    def __init__(self, msg=None, code=None, error_code=None,
                 headers=None):
        if code:
            self.code = code
        if error_code:
            self.error_code = error_code
        if msg:
            self.msg = msg
        super(APIException, self).__init__(msg, None)

    # 自定义更改模块内容,默认是 text/html
    # 下面更改为json内容
    # 参照:C:/Users/roy/.virtualenvs/govtool_api-NTdE09zx/Lib/site-packages/werkzeug/exceptions.py
    def get_body(self, environ=None):
        body = dict(
            msg=self.msg,
            error_code=self.error_code,
            request=request.method + ' ' + self.get_url_no_param() # 方法里面调用静态方法
        )
        text = json.dumps(body)
        return text

    def get_headers(self, environ=None):
        """Get a list of headers."""
        return [('Content-Type', 'application/json')]

    @staticmethod
    def get_url_no_param():
        full_path = str(request.full_path)
        main_path = full_path.split('?')
        return main_path[0]

class A:
    # 静态属性
    total = 0
    _phone = '暂未设置号码'
    def __init__(self, name):
        A.total += 1
        self.__private_attr = '这是一个私有属性'
        self.name = name

    # 私有方法
    def __privateFuc(self):
        print('私有方法')
        print('私有属性: ', self.__private_attr)
        variable = self.getTotal()
        print(variable)

    def set_name(self, name):
        self.__privateFuc()
        self.name = name

    @property
    def phoneNumber(self):
        return self._phone

    # 用户密码加密
    @phoneNumber.setter
    def phoneNumber(self, raw):
        self._phone = raw

    # 静态方法,不用加 self
    # 其他都要
    @staticmethod
    def getTotal():
        print('getTotal 这是静态方法, 静态属性total:', A.total)
        return '方法里面调用静态方法'

    # 类方法
    @classmethod
    def getTotalCls(cls):
        print('getTotal 这是类方法法, 静态属性total:', cls.total)

man = A('roy')
man2 = A('jazz')
print('----get set方法:电话号码-----')
print(man.phoneNumber) # 暂未设置号码
man.phoneNumber = '8831684'
print(man.phoneNumber) # 8831684
print('----类静态属性、方法-----')
man.set_name('roben')
# 私有方法
# 私有属性:  这是一个私有属性
# getTotal 这是静态方法, 静态属性total: 2

# 方法里面调用静态方法
man.getTotal() # getTotal 这是静态方法, 静态属性total: 2
A.getTotal() # getTotal 这是静态方法, 静态属性total: 2
man.getTotalCls() # getTotal 这是类方法法, 静态属性total: 2
A.getTotalCls() # getTotal 这是类方法法, 静态属性total: 2
print(A.total) # 2

你可能感兴趣的:(python 类 和ES6 类的对比)