📄 pyobject.java
字号:
// Copyright (c) Corporation for National Research Initiativespackage org.python.core;/** * All objects known to the Jython runtime system are represented * by an instance of the class <code>PyObject</code> or one of * its subclasses. * * @author Jim Hugunin - hugunin@python.org * @version 1.1, 1/5/98 * @since JPython 0.0 **/public class PyObject implements java.io.Serializable { /** * The Python class of this object. * Unlike in CPython, all types have this attribute, even builtins. * This should only be set in the constructor, never modified otherwise. **/ public transient PyClass __class__; /* must instantiate __class__ when de-serializing */ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { in.defaultReadObject(); __class__ = PyJavaClass.lookup(getClass()); } // A package private constructor used by PyJavaClass PyObject(boolean fakeArgument) { __class__ = (PyClass)this; } /** * The standard constructor for a <code>PyObject</code>. It will set * the <code>__class__</code> field to correspond to the specific * subclass of <code>PyObject</code> being instantiated. **/ public PyObject() { PyClass c = getPyClass(); if (c == null) c = PyJavaClass.lookup(getClass()); __class__ = c; } /** * This method is provided to efficiently initialize the __class__ * attribute. If the following boilerplate is added to a subclass of * PyObject, the instantiation time for the object will be greatly * reduced. * * <blockquote><pre> * // __class__ boilerplate -- see PyObject for details * public static PyClass __class__; * protected PyClass getPyClass() { return __class__; } * </pre></blockquote> * * With PyIntegers this leads to a 50% faster instantiation time. * This replaces the PyObject(PyClass c) constructor which is now * deprecated. **/ protected PyClass getPyClass() { return null; } /** * #### This method is now deprecated and will go away in the future ####. * <p> * A more sophisticated constructor for a <code>PyObject</code>. * Can be more efficient as it allows the subclass of PyObject to * cache its known <code>__class__</code>. * <p> * The common idiom for using this constructor is shown as used for the * PyInteger class: * <blockquote><pre> * public static PyClass __class__; * public PyInteger(int v) { * super(__class__); * ... * </pre></blockquote> * * @param c a <code>PyClass</code> instance giving the * <code>__class__</code> of the new <code>PyObject</code> * @deprecated see get PyClass for details **/ protected PyObject(PyClass c) { if (c == null) { c = PyJavaClass.lookup(getClass()); } __class__ = c; } /** * Equivalent to the standard Python __repr__ method. This method * should not typically need to be overrriden. The easiest way to * configure the string representation of a <code>PyObject</code> is to * override the standard Java <code>toString</code> method. **/ public PyString __repr__() { return new PyString(toString()); } public String safeRepr() throws PyIgnoreMethodTag { if (__class__ == null) { return "unknown object"; } String name = __class__.__name__; PyObject tmp; if (name == null) return "unknown object"; if ((name.equals("org.python.core.PyClass") || name.equals("org.python.core.PyJavaClass")) && (this instanceof PyClass)) { name = ((PyClass)this).__name__; if (name == null) return "unknown class"; return "class '"+name+"'"; } if (name.equals("org.python.core.PyModule")) { tmp = this.__findattr__("__name__"); if (tmp == null) return "unnamed module"; return "module '"+tmp+"'"; } if (name.equals("org.python.core.PyJavaPackage") && (this instanceof PyJavaPackage)) { name = ((PyJavaPackage)this).__name__; if (name == null) return "unnamed java package"; return "java package '"+name+"'"; } return "instance of '"+name+"'"; } /** * Equivalent to the standard Python __str__ method. This method * should not typically need to be overridden. The easiest way to * configure the string representation of a <code>PyObject</code> is to * override the standard Java <code>toString</code> method. **/ public PyString __str__() { return __repr__(); } /** * Equivalent to the standard Python __hash__ method. This method can * not be overridden. Instead, you should override the standard Java * <code>hashCode</code> method to return an appropriate hash code for * the <code>PyObject</code>. **/ public final PyInteger __hash__() { return new PyInteger(hashCode()); } public int hashCode() { return System.identityHashCode(this); } /** * Should almost never be overridden. * If overridden, it is the subclasses responsibility to ensure that * <code>a.equals(b) == true</code> iff <code>cmp(a,b) == 0</code> **/ public boolean equals(Object ob_other) { return (ob_other instanceof PyObject) && _eq((PyObject)ob_other).__nonzero__(); } /** * Equivalent to the standard Python __nonzero__ method. * Returns whether of not a given <code>PyObject</code> is * considered true. **/ public boolean __nonzero__() { return true; } /** * Equivalent to the Jython __tojava__ method. * Tries to coerce this object to an instance of the requested Java class. * Returns the special object <code>Py.NoConversion</code> * if this <code>PyObject</code> can not be converted to the * desired Java class. * * @param c the Class to convert this <code>PyObject</code> to. **/ public Object __tojava__(Class c) { if (c.isInstance(this)) return this; return Py.NoConversion; } /** * The basic method to override when implementing a callable object. * * The first len(args)-len(keywords) members of args[] are plain * arguments. The last len(keywords) arguments are the values of the * keyword arguments. * * @param args all arguments to the function (including * keyword arguments). * @param keywords the keywords used for all keyword arguments. **/ public PyObject __call__(PyObject args[], String keywords[]) { throw Py.TypeError("call of non-function (" + safeRepr() + ")"); } /** * A variant of the __call__ method with one extra initial argument. * This variant is used to allow method invocations to be performed * efficiently. * * The default behavior is to invoke <code>__call__(args, * keywords)</code> with the appropriate arguments. The only reason to * override this function would be for improved performance. * * @param arg1 the first argument to the function. * @param args the last arguments to the function (including * keyword arguments). * @param keywords the keywords used for all keyword arguments. **/ public PyObject __call__(PyObject arg1, PyObject args[], String keywords[]) { PyObject[] newArgs = new PyObject[args.length+1]; System.arraycopy(args, 0, newArgs, 1, args.length); newArgs[0] = arg1; return __call__(newArgs, keywords); } /** * A variant of the __call__ method when no keywords are passed. The * default behavior is to invoke <code>__call__(args, keywords)</code> * with the appropriate arguments. The only reason to override this * function would be for improved performance. * * @param args all arguments to the function. **/ public PyObject __call__(PyObject args[]) { return __call__(args, Py.NoKeywords); } /** * A variant of the __call__ method with no arguments. The default * behavior is to invoke <code>__call__(args, keywords)</code> with the * appropriate arguments. The only reason to override this function * would be for improved performance. **/ public PyObject __call__() { return __call__(Py.EmptyObjects, Py.NoKeywords); } /** * A variant of the __call__ method with one argument. The default * behavior is to invoke <code>__call__(args, keywords)</code> with the * appropriate arguments. The only reason to override this function * would be for improved performance. * * @param arg0 the single argument to the function. **/ public PyObject __call__(PyObject arg0) { return __call__(new PyObject[] {arg0}, Py.NoKeywords); } /** * A variant of the __call__ method with two arguments. The default * behavior is to invoke <code>__call__(args, keywords)</code> with the * appropriate arguments. The only reason to override this function * would be for improved performance. * * @param arg0 the first argument to the function. * @param arg1 the second argument to the function. **/ public PyObject __call__(PyObject arg0, PyObject arg1) { return __call__(new PyObject[] {arg0, arg1}, Py.NoKeywords); } /** * A variant of the __call__ method with three arguments. The default * behavior is to invoke <code>__call__(args, keywords)</code> with the * appropriate arguments. The only reason to override this function * would be for improved performance. * * @param arg0 the first argument to the function. * @param arg1 the second argument to the function. * @param arg2 the third argument to the function. **/ public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2) { return __call__(new PyObject[] {arg0, arg1, arg2}, Py.NoKeywords); } /** * A variant of the __call__ method with four arguments. The default * behavior is to invoke <code>__call__(args, keywords)</code> with the * appropriate arguments. The only reason to override this function * would be for improved performance. * * @param arg0 the first argument to the function. * @param arg1 the second argument to the function. * @param arg2 the third argument to the function. * @param arg3 the fourth argument to the function. **/ public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2, PyObject arg3) { return __call__(new PyObject[] {arg0, arg1, arg2, arg3}, Py.NoKeywords); } /** @deprecated **/ public PyObject _callextra(PyObject[] args, String[] keywords, PyObject starargs, PyObject kwargs) { int argslen = args.length; int nstar = 0; String name = ""; if (this instanceof PyFunction) name = ((PyFunction) this).__name__ + "() "; if (kwargs != null) { PyObject keys = kwargs.__findattr__("keys"); if (keys == null) throw Py.TypeError(name + "argument after ** must be " + "a dictionary"); for (int i = 0; i < keywords.length; i++) if (kwargs.__finditem__(keywords[i]) != null) throw Py.TypeError(name + "got multiple values for " + "keyword argument '" + keywords[i] + "'"); argslen += kwargs.__len__(); } if (starargs != null) { if (!(starargs instanceof PySequence || starargs instanceof PyInstance)) throw Py.TypeError(name + "argument after * must " + "be a sequence"); nstar = starargs.__len__(); argslen += nstar; } PyObject[] newargs = new PyObject[argslen]; int argidx = args.length - keywords.length; System.arraycopy(args, 0, newargs, 0, argidx); if (starargs != null) { PyObject a; for (int i = 0; (a = starargs.__finditem__(i)) != null && i < nstar; i++) { newargs[argidx++] = a; } } System.arraycopy(args, args.length - keywords.length, newargs, argidx, keywords.length); argidx += keywords.length; if (kwargs != null) { String[] newkeywords = new String[keywords.length + kwargs.__len__()]; System.arraycopy(keywords, 0, newkeywords, 0, keywords.length); PyObject keys = kwargs.invoke("keys"); PyObject key; for (int i = 0; (key = keys.__finditem__(i)) != null; i++) { if (!(key instanceof PyString)) throw Py.TypeError(name + "keywords must be strings"); newkeywords[keywords.length + i] = ((PyString) key).internedString(); newargs[argidx++] = kwargs.__finditem__(key); } keywords = newkeywords; } if (newargs.length != argidx) { args = new PyObject[argidx]; System.arraycopy(newargs, 0, args, 0, argidx); } else args = newargs; return __call__(args, keywords); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -