У меня может быть две функции init в классе Python?

Я портирую некоторую геолокацию код Java из http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates#Java (показанный ниже) к Python. Это может быть инициализировано с помощью двух функций (fromDegrees или fromRadians). Я думал, что мог сделать что-то как

class geoLocation:

    _radLat = 0
    _radLong = 0
    _degLat = 0
    _degLong = 0


    def fromDegrees(lat, long):
        #set _radLat, _radLong, _degLat, _degLong

    def fromRadians(lat, long):
        #set _radLat, _radLong, _degLat, _degLong

    ...

Но это не кажется оптимальным, так как я установил значения для _radLat, _radLong, _degLat и _degLong дважды. Я могу определить две функции init? Что лучший способ состоит в том, чтобы сделать это?

Спасибо

/**
 * 

Represents a point on the surface of a sphere. (The Earth is almost * spherical.)

* *

To create an instance, call one of the static methods fromDegrees() or * fromRadians().

* *

This code was originally published at * * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates#Java.

* * @author Jan Philip Matuschek * @version 27 May 2010 */ public class GeoLocation { private double radLat; // latitude in radians private double radLon; // longitude in radians private double degLat; // latitude in degrees private double degLon; // longitude in degrees private static final double MIN_LAT = Math.toRadians(-90d); // -PI/2 private static final double MAX_LAT = Math.toRadians(90d); // PI/2 private static final double MIN_LON = Math.toRadians(-180d); // -PI*2 private static final double MAX_LON = Math.toRadians(180d); // PI*2 private GeoLocation () { } /** * @param latitude the latitude, in degrees. * @param longitude the longitude, in degrees. */ public static GeoLocation fromDegrees(double latitude, double longitude) { GeoLocation result = new GeoLocation(); result.radLat = Math.toRadians(latitude); result.radLon = Math.toRadians(longitude); result.degLat = latitude; result.degLon = longitude; result.checkBounds(); return result; } /** * @param latitude the latitude, in radians. * @param longitude the longitude, in radians. */ public static GeoLocation fromRadians(double latitude, double longitude) { GeoLocation result = new GeoLocation(); result.radLat = latitude; result.radLon = longitude; result.degLat = Math.toDegrees(latitude); result.degLon = Math.toDegrees(longitude); result.checkBounds(); return result; } private void checkBounds() { if (radLat < MIN_LAT || radLat > MAX_LAT || radLon < MIN_LON || radLon > MAX_LON) throw new IllegalArgumentException(); } /** * @return the latitude, in degrees. */ public double getLatitudeInDegrees() { return degLat; } /** * @return the longitude, in degrees. */ public double getLongitudeInDegrees() { return degLon; } /** * @return the latitude, in radians. */ public double getLatitudeInRadians() { return radLat; } /** * @return the longitude, in radians. */ public double getLongitudeInRadians() { return radLon; } @Override public String toString() { return "(" + degLat + "\u00B0, " + degLon + "\u00B0) = (" + radLat + " rad, " + radLon + " rad)"; } /** * Computes the great circle distance between this GeoLocation instance * and the location argument. * @param radius the radius of the sphere, e.g. the average radius for a * spherical approximation of the figure of the Earth is approximately * 6371.01 kilometers. * @return the distance, measured in the same unit as the radius * argument. */ public double distanceTo(GeoLocation location, double radius) { return Math.acos(Math.sin(radLat) * Math.sin(location.radLat) + Math.cos(radLat) * Math.cos(location.radLat) * Math.cos(radLon - location.radLon)) * radius; } /** *

Computes the bounding coordinates of all points on the surface * of a sphere that have a great circle distance to the point represented * by this GeoLocation instance that is less or equal to the distance * argument.

*

For more information about the formulae used in this method visit * * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates.

* @param distance the distance from the point represented by this * GeoLocation instance. Must me measured in the same unit as the radius * argument. * @param radius the radius of the sphere, e.g. the average radius for a * spherical approximation of the figure of the Earth is approximately * 6371.01 kilometers. * @return an array of two GeoLocation objects such that:
    *
  • The latitude of any point within the specified distance is greater * or equal to the latitude of the first array element and smaller or * equal to the latitude of the second array element.
  • *
  • If the longitude of the first array element is smaller or equal to * the longitude of the second element, then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element and smaller or * equal to the longitude of the second array element.
  • *
  • If the longitude of the first array element is greater than the * longitude of the second element (this is the case if the 180th * meridian is within the distance), then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element * or smaller or equal to the longitude of the second * array element.
  • *
*/ public GeoLocation[] boundingCoordinates(double distance, double radius) { if (radius < 0d || distance < 0d) throw new IllegalArgumentException(); // angular distance in radians on a great circle double radDist = distance / radius; double minLat = radLat - radDist; double maxLat = radLat + radDist; double minLon, maxLon; if (minLat > MIN_LAT && maxLat < MAX_LAT) { double deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat)); minLon = radLon - deltaLon; if (minLon < MIN_LON) minLon += 2d * Math.PI; maxLon = radLon + deltaLon; if (maxLon > MAX_LON) maxLon -= 2d * Math.PI; } else { // a pole is within the distance minLat = Math.max(minLat, MIN_LAT); maxLat = Math.min(maxLat, MAX_LAT); minLon = MIN_LON; maxLon = MAX_LON; } return new GeoLocation[]{fromRadians(minLat, minLon), fromRadians(maxLat, maxLon)}; } }

6
задан jul 28 June 2010 в 17:52
поделиться

4 ответа

Выберите одно значение по умолчанию (радианы или градусы) и придерживайтесь его. Вы можете написать метод класса для автоматического преобразования в другой:

class geoLocation:
    def __init__(self, lat, long):
        """init class from lat,long as radians"""

    @classmethod
    def fromDegrees(cls, dlat, dlong):
        """creat `cls` from lat,long in degrees """
        return cls( to_radians(dlat), to_radians(dlong))

    @classmethod
    def fromRadians(cls, lat, long): # just in case
        return cls(lat, long)

obj = geoLocation.fromDegrees(10,20) # returns a new geoLocation object
16
ответ дан 8 December 2019 в 04:27
поделиться

Я бы просто включил булево значение в метод init. Вместо двух методов __init__ сделайте следующее:

class geoLocation:
    def __init__(self, lat, long, degrees=True):
        if degrees:
            # process as fromDegrees
            (self._radLat, self._radLong, self._degLat, self._degLong) = self.fromDegrees(lat, long)
        else:
            (self._radLat, self._radLong, self._degLat, self._degLong) = self.fromRadians(lat, long)

    def fromDegrees(self, lat, long):
        # some function returning radLat and long and degLat and long in a tuple
    def fromRadians(self, lat, long):
        # same idea but different calculations
5
ответ дан 8 December 2019 в 04:27
поделиться

Другой вариант - иметь подклассы GeoLocation , например DegreesGeoLocation и RadiansGeoLocation . Теперь вы можете дать каждому отдельную функцию инициализации.

Теперь вы дважды сохраняете местоположение в своем классе, один раз в радианах, а второй в градусах. Это может вызвать проблемы, если вы случайно измените одно представление, но забудете о другом. Я думаю, вы могли бы лучше всего использовать одно представление и предоставить геттеры и сеттеры, которые в конечном итоге выполняют преобразование в другое представление.

1
ответ дан 8 December 2019 в 04:27
поделиться

Можно использовать методы фабричного класса:

class geoLocation(object):
    @classmethod
    def fromDegrees(cls, lat, long):
        return cls(lat, long, True)

    @classmethod
    def fromDegrees(cls, lat, long):
        return cls(lat, long, False)

    def __init__(self, lat, long, degrees=True):
        if degrees:
            #blah
        else:
            #blah
3
ответ дан 8 December 2019 в 04:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: