Python'da bir fonksiyonun iki argümanı nasıl aktarılır?


11

Python işlevine yapılan bir çağrıda iki bağımsız değişkeni nasıl değiştirebilirim?

pointBu iki argüman arasındaki boşluğu koyarsam :

self.assertEqual(json.loads(some.data), json_data)

ve sonra M-t( transpose-words), anladım:

self.assertEqual(json.loads(some.json), data_data)

Öte yandan CMt ( transpose-sexps) ile :

self.assertEqual(json.loadsjson_data, (some.data))

Ne istiyorum:

self.assertEqual(json_data, json.loads(some.data))

Bunu yapacak bir komut var mı?


2
Ben denemedim ama Bağlantılı Aktarma bunun için kullanılabilir; yine de bu 2 adımlı bir süreçtir.
Kaushal Modi

transpose-subrBir forwardişlevi alan ve onu bir transposeişleve çeviren denilen bir çekirdek işlev vardır . Yani (eğer c-forward-arglistbir fonksiyon argümanından diğerine geçme fonksiyonu - AFAICT bu mevcut olmasaydı) olurdu c-transpose-arglist.
Brendan

Yanıtlar:


4

Bu da uzun zamandır sahip olmak istediğim bir şey ve burada üzerinde çalışmak için biraz motivasyon buldum. Muhtemelen çok sağlam değil, ama ilk denemede denediğim vakaları kapsıyor gibi görünüyor:

(defun my/calculate-stops ()
  (save-excursion
    (let ((start
           (condition-case e
               (while t (backward-sexp))
             (error (point))))
          stops)
      (push start stops)
      (condition-case e
          (while t
            (forward-sexp)
            (when (looking-at "\\s-*,")
              (push (point) stops)))
        (error (push (point) stops)))
      (nreverse stops))))

(defun my/transpose-args ()
  (interactive)
  (when (looking-at "\\s-") (backward-sexp))
  (cl-loop with p = (point)
           with previous = nil
           for stop on (my/calculate-stops)
           for i upfrom 0
           when (<= p (car stop)) do
           (when previous
             (let* ((end (cadr stop))
                    (whole (buffer-substring previous end))
                    middle last)
               (delete-region previous end)
               (goto-char previous)
               (setf middle (if (> i 1) (- (car stop) previous)
                              (string-match "[^, \\t]" whole 
                                            (- (car stop) previous)))
                     last (if (> i 1) (substring whole 0 middle)
                            (concat (substring whole (- (car stop) previous) middle)
                                    (substring whole 0 (- (car stop) previous)))))
               (insert (substring whole middle) last)))
           (cl-return)
           end do (setf previous (car stop))))

Nokta uzayda olduğunda bunu alıyorum (virgül üzerinde çalışırken): let *: Yanlış tür argümanı: integer-or-marker-p, nil
Croad Langshan

@CroadLangshan düzeltme nispeten kolaydı (yukarıya bakın). Bir alternatif yazarak Stefan'ın tavsiyelerini takip etmeye çalıştığım komik şey forward-sexp-function, virgül yüzünden çok hantal gibi görünüyordu. Daha sonra traspose-sexpaynı şeyi yapmak için taklitçiyi denedim ve yine virgülleri hesaba katmak zorunda kaldım. Sınırlayıcıları listelemek için bunun her zaman doğru şeyi yaptığını iddia etmiyorum, belki sadece yarısı ...
wvxvw

Bu (aa, bb), imleç ilk üzerindeyken başarısız olur a. Bu aynı zamanda aktarım için de işe yaramıyor. FOO(aaa *, bbb, ccc)Bir *şekilde aktarımı bozuyor.
'19

Ayrıca başarısız olur FOO(&aaa, bbb)(& takas olmaz).
22

4

transpose-sexpsVirgüllerle ayrılmış şeyleri tanımladığınız ve aktardığınız veya düzenli olarak yaptığınız durumu arayan bir varyasyon kullanıyorum transpose-sexps. Ayrıca imleci ileri doğru sürüklemek yerine yerinde bırakır, ki bu biraz farklıdır ama ben şahsen seviyorum.

(defun my-transpose-sexps ()
  "If point is after certain chars transpose chunks around that.
Otherwise transpose sexps."
  (interactive "*")
  (if (not (looking-back "[,]\\s-*" (point-at-bol)))
      (progn (transpose-sexps 1) (forward-sexp -1))
    (let ((beg (point)) end rhs lhs)
      (while (and (not (eobp))
                  (not (looking-at "\\s-*\\([,]\\|\\s)\\)")))
        (forward-sexp 1))
      (setq rhs (buffer-substring beg (point)))
      (delete-region beg (point))
      (re-search-backward "[,]\\s-*" nil t)
      (setq beg (point))
      (while (and (not (bobp))
                  (not (looking-back "\\([,]\\|\\s(\\)\\s-*" (point-at-bol))))
        (forward-sexp -1))
      (setq lhs (buffer-substring beg (point)))
      (delete-region beg (point))
      (insert rhs)
      (re-search-forward "[,]\\s-*" nil t)
      (save-excursion
        (insert lhs)))))

Benim için bu, assertEqual çağrısının başında boşluk bırakıyor (boşluktaki noktadan başlayarak).
Croad Langshan

1
Bu, aşağıdakiler gibi anahtar kelime bağımsız değişkenleri için işe yaramaz: f(a=1, b=2)(etrafında
aktarır

1
Soru C kodu üzerindeyken, bu cevap şu şekilde çalışır f(a=1, b=2)- emacs.stackexchange.com/a/47930/2418
ideasman42

2

SMIE kullanan modlarda, transpose-sexpbu durumda doğru çalışmalıdır. Infix sembolü ("ayırıcı" olarak da bilinir) bir ,(veya a ;) değil, bir kelime (ör. and) Olduğunda yine de başarısız olurlar .

Yani, bence bunun için komut transpose-sexpve bu doğru çalışmadığında, bir hata olarak görüyorum (ancak zor ve / veya düzeltilmesi ve düşük önceliğe sahip olması gereken bir hata. t Nefesini tut). Bunu düzeltmenin yolu forward-sexp-function, "bir virgül gördükten sonra, tüm argümanın etrafından atladığımı" bilecek bir fonksiyona ayarlamaktır .


1
Java modu (örneğin) SMIE kullanmıyor sanırım? Bunu nasıl düzeltebiliriz?
Samuel Edwin Ward

1
Hayır, C benzeri diller için büyük modlar sadece tarihsel nedenlerle değil SMIE'yi kullanmaz: SMIE'nin ayrıştırıcısı bu diller için çok zayıftır. Bu, SMIE'nin ayrıştırıcısı virgülle ayrılmış iki argümanı (dilbilgisinin bu kısmı yeterince basittir) değiştirmek istiyorsanız, iyi çalışacağını söyledi, bu yüzden sanırım SMIE'yi yapılandırmak ve kullanmak mümkün olacak forward-sexp-functionama SMIE'leri sadece forward-sexp-function yeterince iyi çalıştığı durumlarda kullanmak için bazı kodlar eklemek , çünkü diğer birçok durumda kafa karıştırıcı davranışlara neden olacaktır.
Stefan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.