Y a-t-il un moyen de faire des propriétés de classe en lecture seule à Python? Ex. Dans Unity3D, vous pouvez faire ceci:
class Vector3(object): zero = Vector3(0, 0, 0) ...
7 Réponses :
Ce que vous imaginez est possible, mais pas nécessaire dans ce cas. Attendez juste après que votre classe soit définie pour attribuer l'attribut ou en faites une constante de niveau de module. P> < Il y a une bonne chance que vous voulez simplement Utilisez une forme de forme
(3,) code> NUMPY BANDRAY au lieu d'écrire cette classe, à des fins pratiques. p> p>
La manière la plus évidente pourrait être de modifier l'objet de la classe après le fait: Le problème principal avec ceci est qu'il n'y a alors qu'un seul objet zéro, et s'il est mutable que vous pouvez causer Dommages accidentels partout. Il peut être plus facile (et ressentez moins de hacky) d'utiliser un descripteur dynamique qui crée un vecteur zéro chaque fois qu'il est accessible (cela se fait en créant un ClassProperty classe): p> class Vector3(object):
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
La première réponse est évidente, mais elle n'est pas en lecture seule. Le second nécessite une instance de la classe afin d'utiliser la propriété. Le troisième ne fait pas vraiment ce que je veux ça. Je cherche plus la façon dont l'unité a fait fonctionner.
@Topher corrigé, mais il est étrange de coder les choses d'une manière qui sont étrangers à l'environnement. Les cours de Python ne fonctionnent généralement pas de cette façon.
@topher, en Python, nous n'adorçons pas habituellement des choses comme la lecture seule à un niveau programmatique. Si vous ne donnez aucune raison de réaffecter cette valeur et de ne pas avoir d'intention malveillante, ils ne le feront pas. S'ils sont sortis pour faire de mauvaises choses, vous ne pouvez pas les aider en faisant la chose spéciale-descripteur / métaclass.
"Considérons les autres types mathématiques en Python: INTS, des flotteurs et des nombres complexes. Aucun de ceux-ci n'a un attribut de classe" zéro ", ou un constructeur zéro, ils renvoient à zéro aucun argument." i > C'est une perspicacité fantastique.
@Mike, je veux aussi avoir des propriétés de classe pour les vecteurs de l'unité I, J et K. Ainsi, l'ajout de valeurs par défaut dans la fonction init n'est pas ce que je cherche. Mais la propriété classe est vraiment proche, ce n'est tout simplement pas en lecture seule.
@topher, votre insistance sur la lecture seule est égarée. Ceci est i> nominalement en lecture seule et que je pourrais aussi facilement le changer avec la solution de métaclass. en python, essayant d'appliquer des choses comme "la lecture seule" à un niveau de langue est un gaspillage d'effort. i>
@topher, le fait qu'il pourrait y avoir d'autres constantes d'intérêt n'a pas vraiment d'impact sur la mise en œuvre de votre zéro, une chose pour laquelle Devin recommande une manière avec tonnes i> de précédent. Comme une remarque dans la même veine, vector3 (y = 1) code> pourrait s'avérer mieux que
vecteur3.j code>.
Quant à la partie en lecture seule, Ce est un bon ressource.
template = property(lambda self: self.__template)
Utilisez une métaclass
Les métaclasses ne peuvent pas être multiples héritées ou composées, donc si vous voulez une autre métaclasse de tous les temps, ou une autre superclasse, vous êtes sol. Je les évite généralement.
Les métaclasses peuvent être très utiles, mais on ne semble certainement pas comme l'outil approprié pour ce travail.
@Devin - c'est un argument auto-vaincu. Vous n'obtenez aucune valeur de métaclasses si vous ne les utilisez jamais. Même si vous ne pouviez jamais utiliser une seule métaclass, vous obtiendrez une certaine valeur - plus que si vous ne les utilisez pas du tout simplement parce que vous ne pouvez pas utiliser plusieurs dans certaines situations. Eryksun, belle réponse comme toujours.
@AgF implicitement dans "Je les évite" était "à moins d'être nécessaire". Ce n'est pas un tel cas, car il existe d'autres choses qui produisent un comportement identique mais n'impliquent pas de métaclasses (en particulier, des descripteurs).
Un avantage supplémentaire de cette méthode est que la propriété zéro code> n'apparaît pas sur les instances.
Cela fonctionne assez bien à mes besoins: créer une classe constantes code>.
C'est une question vraiment intéressante, la solution de contournement que j'irais avec est de faire une méthode de classe comme "getter" pour l'objet zéro:
C'est presque ce que je cherche, mais c'est une méthode. Y a-t-il un moyen de faire de cette propriété de classe?
Pas à ma connaissance, de côté de la métataclass Réponse ci-dessus, mais qui provoque zéro pour renvoyer une autre instance vectorielle à chaque fois que vous vous référez, ce que je ne pense pas, c'est ce que vous vouliez (un seul objet défini de manière statique). Honnêtement, c'est vraiment que c'est vraiment une grande quantité d'une différence qui fait "Vecteur3.zero ()" par opposition à "Vecteur3.zero"?
class ClassProperty(property): def __get__(self, cls, owner): return self.fget.__get__(None, owner)() class Vector3(object): _zero = None def __init__(self, x, y, z): self.x = x self.y = y self.z = z @ClassProperty @classmethod def zero(cls): if cls._zero is None: cls._zero = cls(0,0,0) return cls._zero Shamelessly stolen from here
Regardez de plus près la réponse de Devin, il l'a déjà posté devant vous.
@Agf: Je l'ai vu, mais vous pouvez remarquer qu'il a édité sa réponse (voir révisions ) et ce n'était pas comme ça quand j'ai commencé à écrire ma réponse. Merci de le pointer de toute façon ...
Utilisez un Descripteur : Devrait faire ce que vous voulez: p>
Je crois que le paramètre propriétaire code> dans la méthode
__ obtenez __ code> est la classe de possession, de sorte que peut être réécrite comme
le propriétaire de retour (0, 0, 0) code >.